繁体   English   中英

如何决定从输入流中读取多少字节?

[英]How do I decide how many bytes to read from an inputstream?

我正在尝试从InputStream读取。 我写了下面的代码

byte[] bytes = new byte[1024 * 32];
                while (bufferedInStream.read(bytes) != -1) {
                    bufferedOutStream.write(bytes);
                }

我不明白的是我应该在迭代中读取多少字节? 该流包含保存在磁盘上的文件。

在这里阅读但我真的不明白这篇文章。

假设你有一股水从管道流入浴缸。 然后你用一个水桶从浴缸里取水,然后拿着告诉你的花园给草坪浇水。 浴缸是缓冲液。 当您走过草坪时,缓冲区已满,因此当您返回时,有一个满桶可供您再次使用。

如果浴缸很小,那么当您提着桶走路时它可能会溢出,因此您会失去水。 如果你有一个大浴缸,那么它不太可能溢出。 所以更大的缓冲区更方便。 但是当然更大的浴缸会花费更多的钱并占用更多的空间。

程序中的缓冲区占用内存空间。 并且您不想仅仅因为它方便而占用所有可用内存用于缓冲区。

通常在您的读取函数中,您可以指定要读取的字节数。 所以即使你有一个小缓冲区,你也可以这样做(伪代码):

const int bufsize = 50;
buf[bufsize];
unsigned read;
while ((read = is.read(buf, bufsize)) != NULL) {
   // do something with data - up to read bytes
}

在上面的代码中 bufzise 是要读入缓冲区的最大数据。

如果您的读取功能不允许您指定要读取的最大字节数,那么您需要提供一个足够大的缓冲区以接收可能的最大读取量。

因此,最佳缓冲区大小是特定于应用程序的。 只有应用程序开发人员会知道数据的特征。 例如,水流入浴缸的速度有多快。 您能负担得起多大的浴缸尺寸(嵌入式应用程序),您能以多快的速度将水桶从浴缸中穿过花园并返回。

这取决于可用内存、文件大小和其他内容。 你最好做一些测量。

PS:你的代码是错误的。 bufferedInStream.read(bytes)可能不会填满所有缓冲区,而只能填满其中的一部分。 此方法返回实际的字节数作为结果。

byte[] bytes = new byte[1024 * 32];
int size;
while ((size = bufferedInStream.read(bytes)) != -1) {
    bufferedOutStream.write(bytes, 0, size);
}

这是我的建议(假设我们只处理输入流而不是我们将如何写入输出流):

  1. 如果您的用例对高读取性能没有任何要求,请继续使用 FileInputStream。 例如:
FileInputStream fileInputStream = new FileInputStream("filePath");
byte[] bytes = new byte[1024];
int size;
while ((size = fileInputStream.read(bytes)) != -1) {
   outputStream.write(bytes, 0, size);
}
  1. 为了获得更好的读取性能,请使用 BufferedInputStream 并坚持其默认缓冲区大小并一次读取单个字节。 例如:
byte[] bytes = new byte[1];
BufferedInputStream bufferedInputStream = 
                       new BufferedInputStream(fileInputStream("filePath"))
int size;
while ((size = bufferedInputStream.read(bytes)) != -1) {
    outputStream.write(bytes, 0, size);
}
  1. 为了获得更高的性能,请尝试调整 BufferedInputStream 的缓冲区大小并一次读取一个字节。 例如:
byte[] bytes = new byte[1];
BufferedInputStream bufferedInputStream = 
                       new BufferedInputStream(fileInputStream("filePath"), 16048)
int size;
while ((size = bufferedInputStream.read(bytes)) != -1) {
    outputStream.write(bytes, 0, size);
}
  1. 如果您需要更多,请在 BufferedInputStream 之上使用缓冲区。 例如:
byte[] bytes = new byte[1024];
BufferedInputStream bufferedInputStream = 
                       new BufferedInputStream(fileInputStream("filePath"), 16048)
int size;
while ((size = bufferedInputStream.read(bytes)) != -1) {
    outputStream.write(bytes, 0, size);
}

你基本上有一个你指定长度的字节容器(1024 * 32)

然后, inputStream 将尽可能多地填充,可能是完整的容器,在整个迭代过程中迭代,直到它到达文件末尾时它只会填充剩余的字节,并在下一次迭代中返回 -1(它无法读取任何内容) )

因此,您基本上是以 1024*32 字节大小的块从输入复制粘贴到输出

希望它可以帮助您理解代码

顺便说一下,最后一次迭代,如果输入流小于 1024*32,则输出不仅会收到文件的最后一部分,还会收到上次迭代中未填充的字节的前一次迭代内容的重复。

这个想法不是使用缓冲输入流一次读取整个文件内容。 您可以使用缓冲输入流读取与 bytes[] 数组大小一样多的字节。 您消耗读取的字节,然后继续从文件中读取更多字节。 因此,您无需知道文件大小即可阅读它。

这篇文章会更有帮助,因为它解释了为什么应该用缓冲输入流包装文件输入流

为什么使用 BufferedInputStream 比使用 FileInputStream 更快地逐字节读取文件?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM