Java InputStream读取问题

Mic*_*ael 8 java inputstream file

我有一个Java类,我通过InputStream读取数据

    byte[] b = null;
    try {
        b = new byte[in.available()];
        in.read(b);
    } catch (IOException e) {
        e.printStackTrace();
    }
Run Code Online (Sandbox Code Playgroud)

当我从IDE(Eclipse)运行我的应用程序时,它非常有效.

但是当我导出我的项目并将其打包在JAR中时,read命令不会读取所有数据.我该怎么办呢?

当InputStream是File(~10kb)时,通常会发生此问题.

谢谢!

Alv*_*vin 6

通常我更喜欢在从输入流中读取时使用固定大小的缓冲区.正如evilone指出的那样,使用available()作为缓冲区大小可能不是一个好主意,因为,例如,如果您正在读取远程资源,那么您可能事先不知道可用字节.您可以阅读InputStream的javadoc 以获得更多洞察力.

这是我通常用于读取输入流的代码片段:

byte[] buffer = new byte[BUFFER_SIZE];

int bytesRead = 0;
while ((bytesRead = in.read(buffer)) >= 0){
  for (int i = 0; i < bytesRead; i++){
     //Do whatever you need with the bytes here
  }
}
Run Code Online (Sandbox Code Playgroud)

我在这里使用的read()版本将尽可能地填充给定的缓冲区并返回实际读取的字节数.这意味着您的缓冲区可能包含尾随垃圾数据,因此仅使用最多的字节非常重要bytesRead.

注意这一行(bytesRead = in.read(buffer)) >= 0,InputStream规范中没有任何内容表明read()无法读取0个字节.当read()根据您的情况读取0字节作为特殊情况时,您可能需要处理这种情况.对于本地文件,我从未经历过这种情况; 但是,当读取远程资源时,我实际上看到read()不断读取0个字节,导致上面的代码进入无限循环.我通过计算读取0字节的次数解决了无限循环问题,当计数器超过阈值时,我将抛出异常.你可能不会遇到这个问题,但请记住这一点:)

出于性能原因,我可能会远离为每次读取创建新的字节数组.

  • `InputStream.read()`的Javdoc清楚地表明它会阻塞,直到传输至少一个字节或流结束或发生异常.它可以返回零的唯一方法是提供零长度缓冲区或计数. (2认同)

jac*_*bit 5

read()-1InputStream耗尽时将返回。还有一个带有数组的read版本,它允许您进行分块读取。它返回实际读取的字节数或-1输入流的末尾。将其与动态缓冲区(例如ByteArrayOutputStream)结合使用以获取以下内容:

InputStream in = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int read;
byte[] input = new byte[4096];
while ( -1 != ( read = in.read( input ) ) ) {
    buffer.write( input, 0, read );
}
input = buffer.toByteArray()
Run Code Online (Sandbox Code Playgroud)

这大大减少了您必须调用的方法数量,并允许ByteArrayOutputStream更快地增加其内部缓冲区。