假设我试图从这样的Java InputStream中读到:
ZipInputStream zis = new ZipInputStream(new FileInputStream("C:\\temp\\sample3.zip"));
zis.getNextEntry();
byte[] buffer2 = new byte[2];
int count = zis.read(buffer2));
if(count != -1) //process...
else...//something wrong, abort我正在解析一个二进制文件,在本例中,我将缓冲区设置为2,因为我想读下一个简短的内容。如果我想读取其他类型的下一个int等等,我会将缓冲区设置为4大小。问题是,即使我知道有足够的未读数据来填充缓冲区,有时zis.read(缓冲区)也不会填充缓冲区。我可以简单地将整个文件内容转储到一个数组中并对其进行解析,但最后我实现了自己的流读取器,这样做似乎是重新发明了轮子。我还可以实现一个read()函数,该函数检查读取计数,如果小于缓冲区大小,则请求更多数据来填充缓冲区,但这是低效和丑陋的。有更好的方法吗?
以下是以下问题的后续问题:
发布于 2017-04-20 14:51:51
有更好的方法吗?
好吧..。ZipInputStream最终继承自InputStream,因此您应该能够用BufferedInputStream和DataInputStream包装它,并使用readShort、readInt等来读取数据。
就像这样:
while (zis.getNextEntry() != null) {
DataInputStream dis = new DataInputStream(new BufferedInputStream(zis));
boolean done = false;
do {
short s = dis.readShort();
int i = dis.readInt();
...
} while (!done);
}注意:您不应该关闭dis流,因为这会导致zis关闭。(显然,zis需要在外部级别关闭,以避免资源泄漏。)
堆栈中的BufferedInputStream确保您不会在底层流上执行大量的小读取.那就太糟了。
唯一可能的问题是,它的方法对二进制数据的表示方式有特殊的想法;例如,数字是双元的。如果这是一个问题,请考虑将整个zip条目读入一个字节数组,并将其包装在一个ByteBuffer中。
发布于 2017-04-20 14:08:02
您需要检查字节计数并继续读取,直到得到所需的所有信息为止。
zis.getNextEntry();
byte[] buffer2 = new byte[2];
int count = 0;
while (count < 2) {
int bytesRead = zis.read(buffer2, count, 2 - count));
if(bytesRead != -1) {
count += bytesRead;
}
else...//something wrong, abort
}
//process...发布于 2017-04-20 14:32:55
ZipInputStream符合InputStream定义的契约。阅读(byte[].)方法允许并记录为流结束时返回-1,或者返回(1...requested长度)之间的任何值。
而且有很好的理由用这种方式定义API,它使实现可以在不阻塞很长一段时间的情况下返回部分数据,同时等待数据变得可用(想想SocketInputStream)。
如果需要最少数量的数据,则需要反复调用read,直到读取足够多的数据才能继续处理。
至于“低效和丑陋”,通过大容量读取方法读取少量数据会产生自己的开销,并且可能在代码中还显示为您读取的每个数据实体创建一个垃圾byte[]。对于读取少量字节,您可以使用read()方法返回单个字节,该方法在一个简单的实用方法中实现,例如:
static short readShort(InputStream in) throws IOException {
short s = 0;
for (int i=0; i<2; ++i) {
int read = in.read();
if (read < 0)
throw new IOException("unexpected end of stream");
s = (short) ((s << 8) | read);
}
return s;
}(这可以很容易地适应其他原语类型)
单字节I/O在大多数情况下是完全可以接受的,只要您注意确保InputStream被包装到BufferedInputStream中。然后,平均开销减少到BufferedInputStream内部的几个数组索引边界检查。它不会导致对本机数据源的过多调用。
https://stackoverflow.com/questions/43521536
复制相似问题