Java:BufferedInputStream的available()方法问题

opi*_*ike 2 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();
        }
Run Code Online (Sandbox Code Playgroud)

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

我认为behvaior中的这种差异与32位窗口这一事实有关.我将在4.5 GB文件和3.5 GB文件上运行更多测试.如果3.5文件工作而4.5版本不工作,那将进一步证实理论它是32位对64位问题,因为4GB将是阈值.

Voo*_*Voo 7

好吧,如果您阅读javadoc,它会清楚地说明:

返回可以在不阻塞的情况下从此输入流中读取的字节数 (强调我添加)

所以很明显,你想要的并不是这种方法提供的东西.因此,根据底层的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);
} 
Run Code Online (Sandbox Code Playgroud)