OutputStream 类

Java OutputStream 类(java.io.OutputStream)是 Java IO API 中所有输出流的基类。OutputStream 的子类包括 Java BufferedOutputStream 和 Java FileOutputStream 等。要查看输出流的完整列表,请访问 Java IO 概述页面底部的表格。

Java OutputStream 子类

以下是 Java OutputStream 类的一些著名子类:

  • ByteArrayOutputStream

  • FileOutputStream

  • PipedOutputStream

  • BufferedOutputStream

  • FilterOutputStream

  • DataOutputStream

  • PrintStream

  • ObjectOutputStream

输出流和目的地

如 Java IO 概述所述,Java OutputStream 通常连接到某个数据目标,如文件、网络连接、管道、内存缓冲区等。Java IO 概述中对此也有更详细的解释。OutputStream 的数据目标是所有写入 OutputStream 的数据最终结束的地方。

write(byte)

write(byte) 方法用于将单个字节写入 Java OutputStream。OutputStream 的 write() 方法接收一个 int,其中包含要写入的字节的字节值。只有 int 值的第一个字节会被写入。其余部分将被忽略。

OutputStream 的子类可能有其他 write() 方法。例如,DataOutputStream 允许使用相应的 writeBoolean() 和 writeDouble() 方法写入 int、long、float、double、boolean 等 Java 基元数据。

下面是一个 OutputStream write() 示例:

OutputStream outputStream = new FileOutputStream("c:\\data\\output-text.txt");
while(hasMoreData()) {
    int data = getMoreData();
    outputStream.write(data);
}
outputStream.close();

这个 OutputStream write() 示例首先创建了一个 FileOutputStream,并将数据写入其中。然后,示例进入 while 循环。退出 while 循环的条件是方法 hasMoreData() 的返回值。hasMoreData() 的实现没有显示,但可以想象,如果有更多数据要写入,它将返回 true;如果没有,则返回 false。

在 while 循环中,示例调用 getMoreData() 方法获取下一个要写入 OutputStream 的数据,然后将该数据写入 OutputStream。while 循环一直持续到 hasMoreData() 返回 false 为止。

注:为清晰起见,此处略去了正确的异常处理。要了解有关正确异常处理的更多信息,请访问 Java IO 异常处理。

write(byte[])

Java OutputStream 的写入方法可让你一次向 OutputStream 写入一个字节数组。这些写入方法是:

  • write(byte[] bytes)

  • write(byte[] bytes, int offset, int length)

write(byte[] bytes) 方法将字节数组中的所有字节写入 OutputStream。

write(byte[] bytes, int offset, int length) 方法将从字节数组的索引偏移量开始的长度字节写入 OutputStream。

这两种方法都会返回写入 OutputStream 的实际字节数,如果不是整个数组,也可以按要求写入长度字节。

下面是使用这两种写入方法中的第二种将字节数组写入 Java OutputStream 的示例:

OutputStream outputStream = new FileOutputStream("D:\\output.txt");
byte[] sourceBytes = ... // 从某处获取源字节
int bytesWritten = outputStream.write(sourceBytes, 0, sourceBytes.length);

此示例将指示 OutputStream 尝试将 sourceBytes 数组中的所有字节写入 OutputStream。执行此代码后,bytesWritten 变量将包含实际写入 OutputStream 的字节数。

写入性能

将字节数组写入 Java OutputStream 比一次写入一个字节更快。速度的提升可能非常明显,最高可达 10 倍或更多。因此,建议尽可能使用 write(byte[]) 方法。

具体的速度提升取决于运行 Java 代码的计算机的底层操作系统和硬件。速度提升取决于内存速度、硬盘速度和缓冲区大小、网卡速度和缓冲区大小等问题,具体取决于 OutputStream 将数据发送到哪个目的地。

通过 BufferedOutputStream 实现透明缓冲

通过用 Java BufferedOutputStream 对写入 Java OutputStream 的字节进行封装,可以实现透明缓冲。写入 BufferedOutputStream 的所有字节都将首先被缓冲到 BufferedOutputStream 的内部字节数组中。缓冲区满后,缓冲区会被一次性刷新到底层的 OutputStream 中。下面是一个用 BufferedOutputStream 封装 Java OutputStream 的示例:

int bufferSize = 8 * 1024;
OutputStream outputStream =
    new BufferedOutputStream(new FileOutputStream("c:\\data\\output-file.txt"), bufferSize);

有关 BufferedOutputStream 的更多信息,请参阅我的 BufferedOutputStream 教程。

flush()

Java OutputStream 的 flush() 方法会将写入 OutputStream 的所有数据刷新到底层数据目标。例如,如果 OutputStream 是 FileOutputStream,那么写入 FileOutputStream 的字节可能尚未完全写入磁盘。即使你的 Java 代码已将数据写入 FileOutputStream,数据也可能在操作系统内存的某个地方缓冲。通过调用 flush(),你可以确保任何缓冲数据都将被刷新(写入)到磁盘(或网络,或 OutputStream 的其他目标)。下面是一个通过调用 flush() 方法刷新写入 Java OutputStream 的数据的示例:

outputStream.flush();

关闭 OutputStream

一旦完成向 Java OutputStream 写入数据,就应该关闭它。关闭 OutputStream 的方法是调用其 close() 方法。下面是一个关闭 Java OutputStream 的示例:

OutputStream outputStream = new FileOutputStream("c:\\data\\output-text.txt");
while(hasMoreData()) {
    int data = getMoreData();
    outputStream.write(data);
}
outputStream.close();

这里省略了 hasMoreData() 和 getMoreData() 的具体实现,但它们对于理解本示例的原理其实并不十分重要。重要的是,一旦 while 循环结束,向 OutputStream 写入数据的过程结束,就会调用 close() 方法关闭 OutputStream。

不过,上述示例并不完全可靠。如果 write() 方法抛出异常,close() 方法将永远不会被调用。异常将使程序退出上述代码所在的任何方法。

相反,你应该使用 Java try with resources 结构来关闭 OutputStream。下面是一个使用 try with-resources 结构关闭 Java OutputStream 的示例:

try( OutputStream outputStream = new FileOutputStream("c:\\data\\output-text.txt")) {
    while(hasMoreData()) {
        int data = getMoreData();
        outputStream.write(data);
    }
}

一旦退出 try 代码块,就会自动调用 OutputStream 的 close() 方法,因为 OutputStream 是在 try 代码块的括号内声明的。即使在 try 代码块内部出现异常,也会在异常向调用堆栈传播之前调用 close() 方法。

将 OutputStream 转换为 Writer

Java OutputStream 是基于字节的流。你可以使用 Java OutputStreamWriter 类将 OutputStream 转换为基于字符的 Writer。下面是一个使用 OutputStreamWriter 将 Java OutputStream 转换为 Writer 的示例:

OutputStream outputStream = new FileOutputStream("c:\\data\\output.txt");
Writer outputStreamWriter = new OutputStreamWriter(outputStream);
outputStreamWriter.write("Hello World");

你可以在我的 OutputStreamWriter 教程中阅读更多有关如何使用 OutputStreamWriter 的信息,包括如何设置将字符转换为字节时使用的字符编码。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号