Ben*_*nny 14 java zip bytearrayoutputstream bytearrayinputstream zipoutputstream
我如何正确地将字节压缩到a ByteArrayOutputStream然后使用ByteArrayInputStream?读取?我有以下方法:
private byte[] getZippedBytes(final String fileName, final byte[] input) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ZipOutputStream zipOut = new ZipOutputStream(bos);
ZipEntry entry = new ZipEntry(fileName);
entry.setSize(input.length);
zipOut.putNextEntry(entry);
zipOut.write(input, 0, input.length);
zipOut.closeEntry();
zipOut.close();
//Turn right around and unzip what we just zipped
ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(bos.toByteArray()));
while((entry = zipIn.getNextEntry()) != null) {
assert entry.getSize() >= 0;
}
return bos.toByteArray();
}
Run Code Online (Sandbox Code Playgroud)
当我执行此代码时,底部的断言失败,因为entry.size是-1.我不明白为什么提取的实体与压缩的实体不匹配.
Lor*_*uro 14
为什么尺寸为-1?
getNextEntry在ZipInputStream读取条目的开始处调用读取光标的正好位置.
大小(以及其他元数据)存储在实际数据的末尾,因此当光标位于开始时不可用.
只有在您阅读完整个条目数据或只是转到下一个条目后,这些信息才可用.
例如,转到下一个条目:
// position at the start of the first entry
entry = zipIn.getNextEntry();
ZipEntry firstEntry = entry;
// size is not yet available
System.out.println("before " + firstEntry.getSize()); // prints -1
// position at the start of the second entry
entry = zipIn.getNextEntry();
// size is now available
System.out.println("after " + firstEntry.getSize()); // prints the size
Run Code Online (Sandbox Code Playgroud)
或阅读整个条目数据:
// position at the start of the first entry
entry = zipIn.getNextEntry();
// size is not yet available
System.out.println("before " + entry.getSize()); // prints -1
// read the whole entry data
while(zipIn.read() != -1);
// size is now available
System.out.println("after " + entry.getSize()); // prints the size
Run Code Online (Sandbox Code Playgroud)
您的误解很常见,并且有许多关于此问题的错误报告(关闭为"非问题"),如JDK-4079029, JDK-4113731,JDK-6491622.
正如错误报告中所提到的,您可以使用ZipFile而不是ZipInputStream允许在访问条目数据之前获取大小信息; 但要创建一个ZipFile你需要一个File(参见构造函数)而不是一个字节数组.
例如:
File file = new File( "test.zip" );
ZipFile zipFile = new ZipFile(file);
Enumeration enumeration = zipFile.entries();
while (enumeration.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry) enumeration.nextElement();
System.out.println(zipEntry.getSize()); // prints the size
}
Run Code Online (Sandbox Code Playgroud)
如何从输入流中获取数据?
如果要检查解压缩的数据是否等于原始输入数据,可以从输入流中读取,如下所示:
byte[] output = new byte[input.length];
entry = zipIn.getNextEntry();
zipIn.read(output);
System.out.println("Are they equal? " + Arrays.equals(input, output));
// and if we want the size
zipIn.getNextEntry(); // or zipIn.read();
System.out.println("and the size is " + entry.getSize());
Run Code Online (Sandbox Code Playgroud)
现在output应该有相同的内容input.