Java中inputstream和outputstream的用法

发布时间:2021-08-12 09:24:02 作者:chen
来源:亿速云 阅读:179
# Java中InputStream和OutputStream的用法

## 一、概述

在Java中,`InputStream`和`OutputStream`是Java I/O系统中的两个核心抽象类,位于`java.io`包中。它们分别代表字节输入流和字节输出流,是处理字节数据的基础类。几乎所有与字节I/O相关的类都继承自这两个类。

### 1.1 流的概念
流(Stream)可以看作是一个连续的数据序列。在Java I/O中:
- **输入流**:将数据从外部(如文件、网络等)读取到程序中
- **输出流**:将数据从程序写入到外部目的地

### 1.2 字节流 vs 字符流
Java I/O系统分为两大体系:
- 字节流:以`InputStream`和`OutputStream`为代表,处理8位字节
- 字符流:以`Reader`和`Writer`为代表,处理16位Unicode字符

本文主要讨论字节流的使用。

## 二、InputStream详解

### 2.1 核心方法

```java
public abstract class InputStream implements Closeable {
    // 读取下一个字节,返回0-255的int值,到达末尾返回-1
    public abstract int read() throws IOException;
    
    // 读取多个字节到字节数组b,返回实际读取的字节数
    public int read(byte b[]) throws IOException;
    
    // 读取最多len个字节到字节数组b的off位置开始处
    public int read(byte b[], int off, int len) throws IOException;
    
    // 跳过并丢弃n个字节,返回实际跳过的字节数
    public long skip(long n) throws IOException;
    
    // 返回可读取(或跳过)的估计字节数
    public int available() throws IOException;
    
    // 关闭流并释放相关资源
    public void close() throws IOException;
    
    // 标记当前位置,readlimit表示标记的有效范围
    public synchronized void mark(int readlimit);
    
    // 重置到上次标记的位置
    public synchronized void reset() throws IOException;
    
    // 测试是否支持mark/reset
    public boolean markSupported();
}

2.2 常用子类

子类 描述
FileInputStream 从文件读取数据的输入流
ByteArrayInputStream 从字节数组读取数据的输入流
PipedInputStream 与PipedOutputStream配合使用的管道输入流
FilterInputStream 装饰器模式的基类,如BufferedInputStream
ObjectInputStream 用于反序列化对象的输入流
SequenceInputStream 将多个输入流合并为一个

2.3 使用示例

示例1:基本读取操作

try (InputStream is = new FileInputStream("test.txt")) {
    int data;
    while ((data = is.read()) != -1) {
        System.out.print((char) data);
    }
} catch (IOException e) {
    e.printStackTrace();
}

示例2:缓冲读取

try (InputStream is = new FileInputStream("largefile.bin");
     BufferedInputStream bis = new BufferedInputStream(is)) {
    byte[] buffer = new byte[1024];
    int bytesRead;
    while ((bytesRead = bis.read(buffer)) != -1) {
        // 处理读取的数据
    }
} catch (IOException e) {
    e.printStackTrace();
}

三、OutputStream详解

3.1 核心方法

public abstract class OutputStream implements Closeable, Flushable {
    // 写入一个字节(低8位)
    public abstract void write(int b) throws IOException;
    
    // 写入字节数组b中的所有字节
    public void write(byte b[]) throws IOException;
    
    // 从字节数组b的off位置开始写入len个字节
    public void write(byte b[], int off, int len) throws IOException;
    
    // 刷新输出流,强制写出任何缓冲的输出字节
    public void flush() throws IOException;
    
    // 关闭流并释放相关资源
    public void close() throws IOException;
}

3.2 常用子类

子类 描述
FileOutputStream 向文件写入数据的输出流
ByteArrayOutputStream 向字节数组写入数据的输出流
PipedOutputStream 与PipedInputStream配合使用的管道输出流
FilterOutputStream 装饰器模式的基类,如BufferedOutputStream
ObjectOutputStream 用于序列化对象的输出流
PrintStream 提供各种打印方法的输出流

3.3 使用示例

示例1:基本写入操作

try (OutputStream os = new FileOutputStream("output.txt")) {
    String text = "Hello, OutputStream!";
    os.write(text.getBytes(StandardCharsets.UTF_8));
    os.flush(); // 确保数据被写出
} catch (IOException e) {
    e.printStackTrace();
}

示例2:缓冲写入

try (OutputStream os = new FileOutputStream("largefile.bin");
     BufferedOutputStream bos = new BufferedOutputStream(os)) {
    byte[] data = new byte[1024];
    // 填充数据...
    bos.write(data);
    // 不需要每次调用flush(),BufferedOutputStream会自动处理
} catch (IOException e) {
    e.printStackTrace();
}

四、高级用法与技巧

4.1 装饰器模式的应用

Java I/O流采用了装饰器模式,可以通过组合不同的流来增强功能:

// 组合了缓冲、解压缩和文件输入流
try (InputStream is = new BufferedInputStream(
                      new GZIPInputStream(
                      new FileInputStream("data.gz")))) {
    // 读取处理...
}

4.2 使用try-with-resources

Java 7引入的try-with-resources语法可以自动关闭资源:

try (InputStream in = new FileInputStream("input.txt");
     OutputStream out = new FileOutputStream("output.txt")) {
    byte[] buffer = new byte[1024];
    int length;
    while ((length = in.read(buffer)) != -1) {
        out.write(buffer, 0, length);
    }
}

4.3 大文件处理

对于大文件,应避免一次性读取全部内容:

try (InputStream is = new FileInputStream("hugefile.bin");
     OutputStream os = new FileOutputStream("copy.bin")) {
    byte[] buffer = new byte[8192]; // 8KB缓冲区
    int bytesRead;
    while ((bytesRead = is.read(buffer)) != -1) {
        os.write(buffer, 0, bytesRead);
    }
}

4.4 对象序列化

使用ObjectInputStream/ObjectOutputStream进行对象序列化:

// 写入对象
try (OutputStream os = new FileOutputStream("object.dat");
     ObjectOutputStream oos = new ObjectOutputStream(os)) {
    oos.writeObject(new MySerializableObject());
}

// 读取对象
try (InputStream is = new FileInputStream("object.dat");
     ObjectInputStream ois = new ObjectInputStream(is)) {
    MySerializableObject obj = (MySerializableObject) ois.readObject();
}

五、常见问题与解决方案

5.1 资源泄漏

问题:忘记关闭流会导致资源泄漏
解决:始终使用try-with-resources或确保在finally块中关闭

5.2 性能问题

问题:频繁的小量读写操作性能差
解决:使用缓冲流(BufferedInputStream/BufferedOutputStream)

5.3 字符编码

问题:直接使用字节流处理文本可能导致乱码
解决:对于文本数据,考虑使用字符流(Reader/Writer)或明确指定编码

5.4 文件锁定

问题:多线程/多进程同时访问文件
解决:使用FileLock或适当的同步机制

六、总结

InputStream和OutputStream是Java I/O系统的基石,理解它们的用法对于开发高效、可靠的I/O操作至关重要。关键点包括:

  1. 区分字节流和字符流的适用场景
  2. 掌握基本的读写操作和方法
  3. 合理使用缓冲提高性能
  4. 确保资源的正确关闭
  5. 根据需求选择合适的流组合

随着Java的发展,NIO(New I/O)包提供了更高效的I/O操作方式,但传统的I/O流仍然在许多场景下简单实用。掌握这些基础知识将为更高级的I/O编程打下坚实基础。

注意:本文示例代码基于Java 8及以上版本,在实际开发中应根据具体需求选择合适的实现方式,并注意异常处理和资源管理。 “`

这篇文章大约2500字,涵盖了Java中InputStream和OutputStream的主要用法,包括基本概念、核心方法、常用子类、使用示例、高级技巧和常见问题等内容,采用Markdown格式编写,结构清晰,适合作为技术文档或教程。

推荐阅读:
  1. java中outputstream文件输出流的使用方法
  2. java中枚举的介绍和用法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:sqlmap注入的示例分析

下一篇:phonegap常用事件有哪些

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》