提问人:Jason Watkins 提问时间:6/26/2010 最后编辑:Erik KaplunJason Watkins 更新时间:8/18/2023 访问量:23733
BufferedInputStream 的用法
Usage of BufferedInputStream
问:
让我在这篇文章的开头提出一个警告。在Java方面,我是一个完全的初学者。我已经断断续续地编写 PHP 一段时间了,但我已经准备好制作一个桌面应用程序,所以出于各种原因,我决定使用 Java。
我正在处理的应用程序处于初始阶段(少于 5 个类),我需要从本地文件中读取字节。通常,文件当前小于 512kB(但将来可能会变大)。目前,我正在使用 a 将文件读入三个字节数组,这完全满足了我的要求。但是,我看到了一个提到,并且想知道我目前这样做的方式是否最好,或者我是否也应该使用一个。FileInputStream
BufferedInputStream
BufferedInputStream
我已经做了一些研究,并在这里阅读了一些关于 Stack Overflow 的问题,但我仍然无法理解何时使用和不使用 .在我的情况下,我读入字节的第一个数组只有几个字节(小于 20 个)。如果我收到的数据在这些字节中是好的,那么我会将文件的其余部分读入另外两个不同大小的字节数组中。BufferedInputStream
我还听说很多人提到分析,看看在每种特定情况下哪个更有效,但是,我没有分析经验,我不确定从哪里开始。我也希望得到一些建议。
我很抱歉写了这么长的帖子,但我真的很想学习和理解做这些事情的最佳方法。我总是有一个坏习惯,就是事后猜测我的决定,所以我希望得到一些反馈。谢谢!
答:
BufferedInputStream 会提前读取所需的更多文件。据我了解,它提前做了更多的工作,比如,1 个大的连续磁盘读取与在一个紧密的循环中做很多工作。
就分析而言 - 我喜欢 netbeans 中内置的分析器。这真的很容易上手。:-)
评论
我不能谈论分析,但根据我开发 Java 应用程序的经验,我发现使用任何缓冲区类(BufferedInputStream、StringBuffer)我的应用程序都非常快。正因为如此,我甚至将它们用于最小的文件或字符串操作。
评论
read()
read(byte[])
read()
read(byte[])
BufferedInputStream
如果你使用一个相对较大的数组来一次读取一个块的数据,那么只会引入一个浪费的副本。 (记住,不一定读取所有的数组 - 你可能想要)。获胜的地方在于进行大量小阅读。BufferedInputStream
read
DataInputStream.readFully
BufferedInputStream
评论
ByteArrayInputStream
InputStream
byte[]
byte[]
BufferedInputStream
ByteArrayInputStream
BufferedInputStream
如果您始终如一地进行小读取,那么 a 将为您提供更好的性能。对无缓冲流的每个读取请求通常会导致系统调用操作系统以读取请求的字节数。执行系统调用的开销可能是每个系统调用的数千条机器指令。缓冲流通过对内部缓冲区执行一次大型读取(例如)最多 8k 字节,然后从该缓冲区传出字节来减少这种情况。这可以大大减少系统调用的次数。BufferedInputStream
但是,如果您一直在进行大量读取(例如 8k 或更多),那么 a 会减慢速度。通常不会减少系统调用的数量,缓冲会引入额外的数据复制步骤。BufferedInputStream
在您的用例中(您首先读取一个 20 字节的块,然后读取大量大块),我会说使用 a 更有可能降低性能而不是提高性能。但归根结底,这取决于实际的读取模式。BufferedInputStream
评论
However, if you are consistently doing large reads (e.g. 8k or more) then a BufferedInputStream slows things.
如何?
import java.io.*;
class BufferedInputStream
{
public static void main(String arg[])throws IOException
{
FileInputStream fin=new FileInputStream("abc.txt");
BufferedInputStream bis=new BufferedInputStream(fin);
int size=bis.available();
while(true)
{
int x=bis.read(fin);
if(x==-1)
{
bis.mark(size);
System.out.println((char)x);
}
}
bis.reset();
while(true)
{
int x=bis.read();
if(x==-1)
{
break;
System.out.println((char)x);
}
}
}
}
评论
以下内容非常适合我预填充缓冲的输入流。
private BufferedInputStream readBeforehand(S3Object object) throws IOException {
int length = min(object.getObjectMetadata().getContentLength(), BUFFER_MAX_SIZE);
BufferedInputStream bis = new BufferedInputStream(object.getObjectContent(), length);
bis.mark(length);
for (int i = 0; i < length; i++)
if (bis.read() == EOF) break;
bis.reset();
return bis;
}
评论