Java BufferedOutputStream

时间:2020-01-09 10:36:00  来源:igfitidea点击:

Java BufferedOutputStream类java.io.BufferedOutputStream用于捕获在缓冲区中写入BufferedOutputStream的字节,并将整个缓冲区批量写入底层Java OutputStream中以提高性能。缓冲可以大大提高IO的速度,尤其是在将数据写入磁盘访问或者网络时。

创建一个BufferedOutputStream

要将缓冲添加到OutputStream中,只需将它们包装在BufferedOutputStream中即可。这是一个将OutputStream包装在BufferedOutputStream中的示例:

OutputStream output = new BufferedOutputStream(
                      new FileOutputStream("c:\data\output-file.txt"));

设置BufferedOutputStream的缓冲区大小

我们可以在JavaBufferedOutputStream中设置缓冲区大小以供内部使用。我们将size作为构造函数参数提供,如下所示:

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

本示例将内部缓冲区设置为8 KB。最好使用1024个字节的倍数的缓冲区大小。最适用于硬盘等大多数内置缓冲。

除了在输入流中添加缓冲外,Java的BufferedOutputStream的行为与OutputStream的行为完全相同。唯一的区别是,如果需要绝对确保到目前为止写入的数据已从缓冲区刷新到网络或者磁盘上,则可能需要调用flush()

BufferedOutputStream的最佳缓冲区大小

我们应该使用不同的缓冲区大小进行一些实验,以找出哪种缓冲区大小似乎可以在具体硬件上提供最佳性能。最佳的缓冲区大小可能取决于我们将JavaBufferedOutputStream与磁盘一起使用还是与网络OutputStream一起使用。

对于磁盘流和网络流,最佳缓冲区大小也可能取决于计算机中的具体硬件。如果硬盘一次至少写入4KB,那么使用少于4KB的缓冲区是愚蠢的。然后最好使用4KB的倍数的缓冲区大小。例如,使用6KB也是愚蠢的。

即使磁盘写入例如一次使用4KB,最好使用大于此大小的缓冲区。磁盘擅长顺序写入数据,这意味着它擅长写入彼此相邻的多个块。因此,与仅使用4KB缓冲区相比,将16KB缓冲区或者64KB缓冲区(甚至更大)与" BufferedOutputStream"一起使用可能仍会为我们提供更好的性能。

要找到最佳的" BufferedOutputStream"缓冲区大小,请找出硬盘写入的块大小,然后将缓冲区设为该大小的倍数。我们肯定必须尝试找到最佳的缓冲区大小。通过测量具有不同缓冲区大小的写入速度来做到这一点。

write()

要将数据写入Java的BufferedOutputStream,可以使用其write()方法。 write()方法采用一个int,其中包含要写入的字节的字节值。因此,实际上只有传递的int的低8位被写入了BufferedOutputStream目的地。这是一个使用其write()方法将数据写入Java BufferedOutputStream的示例:

BufferedOutputStream bufferedOutputStream =
    new BufferedOutputStream(new FileOutputStream("c:\data\output-text.txt"));

bufferedOutputStream.write(123);

这个例子将字节值123写入给定的Java BufferedOutputStream中。

写入字节数组

由于Java的BufferedOutputStream是OutputStream的子类,因此我们也可以将字节数组写入BufferedOutputStream,而不是一次只写一个字节。这是一个将字节数组写入JavaBufferedOutputStream的示例:

BufferedOutputStream bufferedOutputStream =
    new BufferedOutputStream(new FileOutputStream("c:\data\output-text.txt"));

byte bytes =  new byte[]{1,2,3,4,5};

outputStream.write(bytes);

flush()

当我们将数据写入Java的" BufferedOutputStream"时,数据会在内部缓存在字节缓冲区中,直到字节缓冲区已满为止,这时整个缓冲区都将写入底层的" OutputStream"中。

如果我们想确保所有写入的数据都写到磁盘上而不必关闭BufferedOutputStream,则可以调用其flush()方法。调用flush()将确保到目前为止所有已写入BufferedOutputStream的数据也已完全写入基础的OutputStream,此外还将在基础上调用flush()。 OutputStream。这是一个调用JavaBufferedOutputStream``flush()方法的示例:

OutputStream outputStream =
    new BufferedOutputStream(new FileOutputStream("c:\data\output-text.txt"));

byte bytes =  new byte[]{1,2,3,4,5};

outputStream.write(bytes);

outputStream.flush()

关闭BufferedOutputStream

一旦完成将数据写入Java" BufferedOutputStream"中,就应该关闭它。通过调用其close()方法来关闭BufferedOutputStream。关闭" BufferedOutputStream"也会关闭" BufferedOutputStream"正在从中读取数据的基础" OutputStream"。这是关闭JavaBufferedOutputStream的示例:

BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                      new FileOutputStream("c:\data\output-file.txt"));

while(hasMoreData()) {
    int data = getMoreData();
    bufferedOutputStream.write(data);
}
bufferedOutputStream.close();

省略了hasMoreData()和getMoreData()的具体实现,但是对于理解本示例的原理而言,它们并不是真正重要的。重要的是,一旦" while"循环结束,并且我们完成了向" BufferedOutputStream"中写入数据,便会调用其" close()"方法,该方法将关闭" BufferedOutputStream"。

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

相反,我们应该使用带有资源构造的Java try来关闭BufferedOutputStream。这是一个使用try-with-resources构造关闭JavaBufferedOutputStream的示例:

try( BufferedOutputStream bufferedOutputStream =
        new BufferedOutputStream(new FileOutputStream("c:\data\output-text.txt"))) {

    while(hasMoreData()) {
        int data = getMoreData();
        output.write(data);
    }
}

一旦退出了try块,就会自动调用BufferedOutputStream的close()方法,因为在try块的括号内声明了BufferedOutputStream。即使从try块内部抛出异常,在将异常传播到调用堆栈之前,仍会调用close()方法。