让我在这篇文章的序言中提出一点警告。对于 Java 来说,我完全是个初学者。我断断续续地编写 PHP 程序有一段时间了,但我准备制作一个桌面应用程序,因此出于各种原因我决定使用 Java。
我正在开发的应用程序处于开始阶段(少于 5 个类),我需要从本地文件读取字节。通常,文件当前小于 512kB(但将来可能会变得更大)。目前,我正在使用
FileInputStream
将文件读入三个字节数组,这完全满足我的要求。然而,我看到提到了 BufferedInputStream
,并且想知道我目前这样做的方式是否最好,或者我是否也应该使用 BufferedInputStream
。
我已经做了一些研究,并在 Stack Overflow 上阅读了一些问题,但我仍然无法理解何时使用和不使用
BufferedInputStream
的最佳情况。在我的情况下,我读入的第一个数组只有几个字节(小于 20)。如果我收到的数据在这些字节中是好的,那么我将文件的其余部分读入另外两个不同大小的字节数组中。
我也听到很多人提到分析,以了解在每种特定情况下哪种方法更有效,但是,我没有分析经验,并且不太确定从哪里开始。我也希望对此有一些建议。
我很抱歉发了这么长的帖子,但我真的很想学习和理解做这些事情的最佳方法。我总是有一个坏习惯,反复猜测我的决定,所以我希望得到一些反馈。谢谢!
如果您持续进行小量读取,那么
BufferedInputStream
将为您带来明显更好的性能。无缓冲流上的每个读取请求通常都会导致对操作系统的系统调用以读取请求的字节数。执行系统调用的开销可能是每个系统调用数千条机器指令。缓冲流通过在内部缓冲区中执行一次大型读取(例如)最多 8k 字节,然后从该缓冲区中分发字节来减少这种情况。这可以大大减少系统调用的次数。
但是,如果您持续进行大量读取(例如 8k 或更多),那么
BufferedInputStream
会稍微减慢速度。您通常不会减少系统调用的数量,并且缓冲会引入额外的数据复制步骤。
在您的用例中(您首先读取 20 字节块,然后读取许多大块),我想说使用
BufferedInputStream
更有可能降低性能而不是提高性能。但最终,这取决于实际的阅读模式。
如果您使用相对较大的数组一次读取一块数据,那么
BufferedInputStream
只会引入浪费的副本。 (请记住,read
不一定读取所有数组 - 您可能需要 DataInputStream.readFully
)。 BufferedInputStream
获胜的地方在于进行大量小读操作。
BufferedInputStream 提前读取您需要的更多文件。据我了解,它提前做了更多的工作,例如,1 个大的连续磁盘读取与在紧密循环中执行许多工作。
就分析而言 - 我喜欢 Netbeans 中内置的分析器。上手真的很容易。 :-)
我无法谈论分析,但根据我开发 Java 应用程序的经验,我发现使用任何缓冲区类 - BufferedInputStream、StringBuffer - 我的应用程序速度都特别快。因此,即使是最小的文件或字符串操作,我也使用它们。
以下内容对我来说非常适合预填充缓冲输入流。
private BufferedInputStream readBeforehand(S3Object object) throws IOException {
int length = (int) min(object.getObjectMetadata().getContentLength(), BUFFER_MAX_SIZE);
BufferedInputStream bis = new BufferedInputStream(object.getObjectContent(), length);
bis.mark(length);
for (int i = 0, b = 0; i < length && b != EOF; i++)
b = bis.read();
bis.reset();
return bis;
}
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);
}
}
}
}