Java:BufferedInputStream 的 available() 方法存在问题

标签 java file-io

我正在处理以下代码,用于将一个大文件拆分为一组较小的文件:

FileInputStream input = new FileInputStream(this.fileToSplit);
            BufferedInputStream iBuff = new BufferedInputStream(input);
            int i = 0;

            FileOutputStream output = new FileOutputStream(fileArr[i]);
            BufferedOutputStream oBuff = new BufferedOutputStream(output);

            int buffSize = 8192;
            byte[] buffer = new byte[buffSize];
            while (true) {
                if (iBuff.available() < buffSize) {
                    byte[] newBuff = new byte[iBuff.available()];
                    iBuff.read(newBuff);
                    oBuff.write(newBuff);
                    oBuff.flush();
                    oBuff.close();

                    break;
                }
                int r = iBuff.read(buffer);

                if (fileArr[i].length() >= this.partSize) {
                    oBuff.flush();
                    oBuff.close();
                    ++i;
                    output = new FileOutputStream(fileArr[i]);
                    oBuff = new BufferedOutputStream(output);
                }
                oBuff.write(buffer);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

这是我看到的奇怪行为...当我使用 3GB 文件运行此代码时,初始 iBuff.available() 调用返回一个大约 2,100,000,000 的值,并且代码工作正常。当我在 12GB 文件上运行此代码时,初始 iBuff.available() 调用仅返回 200,000,000 的值(该值小于分割文件大小 500,000,000,导致处理出错)。

我认为这种行为差异与它是在 32 位 Windows 上有关。我将对 4.5 GB 文件和 3.5 GB 文件运行更多测试。如果 3.5 文件有效而 4.5 文件无效,这将进一步证实这是 32 位与 64 位问题的理论,因为 4GB 将成为阈值。

最佳答案

如果您阅读了 javadoc,它会非常清楚地说明:

Returns the number of bytes that can be read from this input stream without blocking (emphasis added by me)

所以很明显,你想要的并不是这个方法提供的。因此,根据底层的InputStream,您可能会更早地遇到问题(例如,网络上的流与不返回文件大小的服务器 - 您必须读取完整的文件并缓冲它,只是为了返回“正确的”可用文件) () 计数,这会花费很多时间 - 如果您只想读取标题怎么办?)

因此,处理此问题的正确方法是更改​​解析方法,以便能够分段处理文件。就我个人而言,我认为没有太多理由在这里使用 available() - 只需调用 read() 并在 read() 返回 -1 后立即停止应该可以正常工作。如果您想确保每个文件确实包含 blockSize 字节,则可以变得更加复杂 - 如果该场景很重要,只需添加一个内部循环。

int blockSize = XXX;
byte[] buffer = new byte[blockSize];
int i = 0;
int read = in.read(buffer);
while(read != -1) {
   out[i++].write(buffer, 0, read);
   read = in.read(buffer);
} 

关于Java:BufferedInputStream 的 available() 方法存在问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6164853/

相关文章:

java - 更改 boolean 数组中的值。选择地方而不是值(value)

java - 同时将 allure 与 testNG 和 jUnit 一起使用

java - 如何将 BufferedImage 保存为文件

java - 将优先级队列读/写到文本文件的有效方法是什么?

java - Spring 集成: Reading from Kafka Queue

java - 我的 Property Loader 单例线程安全吗?

python - 如何在读取文件内容时写入文本文件的中间部分?

java - 在 java 中读取和存储 .bmp 文件

java - 无法创建煮熟的解析器

java - 客户端的 BufferedInputStream.read() while 循环永远不会停止