Java:从InputStream读取并不总是读取相同数量的数据

时间:2011-10-24 11:11:30

标签: java java-ee file-io zip inputstream

无论好坏,我一直在使用如下代码:

ZipFile aZipFile = new ZipFile(fileName);   
InputStream zipInput = aZipFile.getInputStream(name);  
int theSize = zipInput.available();  
byte[] content = new byte[theSize];  
zipInput.read(content, 0, theSize);

我已经使用过它(获取可用大小并直接读取到字节缓冲区的逻辑)  对于File I / O没有任何问题,我也使用它与zip文件。

但是最近我进入了一个案例,zipInput.read(content, 0, theSize);实际上读取的theSize比可用的zipInput.read(content, 0, theSize);少3个字节。

由于代码不在循环中来检查{{1}}返回的长度,我读取了最后3个字节丢失的文件
后来程序无法正常运行(文件是二进制文件)。

使用较大尺寸的不同zip文件很奇怪,例如1075字节(在我的情况下有问题的zip条目是867字节)代码工作正常!

我明白代码的逻辑可能不是“最好的”,但为什么我现在突然遇到这个问题?

如果我立即使用更大的zip条目运行该程序,该怎么办?

非常欢迎任何意见

由于

3 个答案:

答案 0 :(得分:7)

来自InputStream read API文档:

  

尝试读取len个字节,但数字较小   可能会被阅读。

......和:

  

返回:读入缓冲区的总字节数,如果是,则返回-1   没有更多的数据,因为已经到达了流的末尾。

换句话说,除非read方法返回-1,否则仍有更多数据可供读取,但您不能保证read将读取完全指定的字节数。指定的字节数是上限,用于描述它将读取的最大数据量。

答案 1 :(得分:2)

使用available()并不能保证它计算end of stream的总可用字节数 请参阅Java InputStream's available() method。它说

  

返回此输入流可以读取(或跳过)的字节数的估计值,而不会在下次调用此输入流的方法时阻塞。下一次调用可能是同一个线程或另一个线程。单个读取或跳过这么多字节不会阻塞,但可以读取或跳过更少的字节。

     

请注意,虽然InputStream的某些实现将返回流中的总字节数,但许多实现不会。使用此方法的返回值来分配用于保存此流中所有数据的缓冲区绝对不正确。

您的问题的示例解决方案如下:

ZipFile aZipFile = new ZipFile(fileName);   
InputStream zipInput = aZipFile.getInputStream( caImport );  
int available = zipInput.available();  
byte[] contentBytes = new byte[ available ];  
while ( available != 0 )   
{   
    zipInput.read( contentBytes );   
    // here, do what ever you want  
    available = dis.available();  
} // while available  
...   

这适用于所有大小的输入文件。

答案 2 :(得分:0)

这样做的最好方法应该是风箱:

public static byte[] readZipFileToByteArray(ZipFile zipFile, ZipEntry entry)
    throws IOException {
    InputStream in = null;
    try {
        in = zipFile.getInputStream(entry);
        return IOUtils.toByteArray(in);
    } finally {
        IOUtils.closeQuietly(in);
    }
}

其中IOUtils.toByteArray(in)方法继续读取直到EOF,然后返回字节数组。