Java ZipInputStream 提取错误
Java ZipInputStream extraction errors
下面是一些从仅包含一个文件的 zip 文件中提取文件的代码。但是,提取的文件与通过 WinZip 或其他压缩实用程序提取的同一文件不匹配。如果文件包含奇数个字节,我预计它可能会关闭一个字节(因为我的缓冲区大小为 2,一旦读取失败我就中止)。但是,在分析(使用 WinMerge 或 Diff)使用以下代码提取的文件与通过 Winzip 提取的文件时,Java 提取中有几个区域缺少字节。有谁知道为什么或如何解决这个问题?
package zipinputtest;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipInputStream;
public class test2 {
public static void main(String[] args) {
try {
ZipInputStream zis = new ZipInputStream(new FileInputStream("C:\temp\sample3.zip"));
File outputfile = new File("C:\temp\sample3.bin");
OutputStream os = new BufferedOutputStream(new FileOutputStream(outputfile));
byte[] buffer2 = new byte[2];
zis.getNextEntry();
while(true) {
if(zis.read(buffer2) != -1) {
os.write(buffer2);
}
else break;
}
os.flush();
os.close();
zis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
我能够使用此图像产生错误(将其保存并压缩为 sample3.zip 和 运行 上的代码),但是任何足够大的二进制文件都应该显示差异。
您可以使用更逐字的方式来检查是否所有字节都已读取和写入,例如像
这样的方法
public int extract(ZipInputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE];
int total = 0;
int read;
while ((read = in.read(buffer)) != -1) {
total += read;
out.write(buffer, 0, read);
}
return total;
}
如果在write()
中没有使用read
参数,该方法假定buffer
的全部内容将被写出,这可能不正确,如果buffer
未满
OutputStream
可以在 extract()
方法内部或外部刷新和关闭。调用 close()
就足够了,因为它还调用了 flush()
.
无论如何,Java的"standard" I/O代码,和java.util.zip
包一样,已经过测试和广泛使用,所以它不太可能可能有一个如此根本的错误,以至于很容易导致字节丢失。
while (true) {
if(zis.read(buffer2) != -1) {
os.write(buffer2);
}
else break;
}
常见问题。你忽略了计数。应该是:
int count;
while ((count = zis.read(buffer2)) != -1)
{
os.write(buffer2, 0, count);
}
注意:
- 缓冲区大小为 2 是荒谬的。使用8192或更多。
flush()
在 close()
之前是多余的。
下面是一些从仅包含一个文件的 zip 文件中提取文件的代码。但是,提取的文件与通过 WinZip 或其他压缩实用程序提取的同一文件不匹配。如果文件包含奇数个字节,我预计它可能会关闭一个字节(因为我的缓冲区大小为 2,一旦读取失败我就中止)。但是,在分析(使用 WinMerge 或 Diff)使用以下代码提取的文件与通过 Winzip 提取的文件时,Java 提取中有几个区域缺少字节。有谁知道为什么或如何解决这个问题?
package zipinputtest;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipInputStream;
public class test2 {
public static void main(String[] args) {
try {
ZipInputStream zis = new ZipInputStream(new FileInputStream("C:\temp\sample3.zip"));
File outputfile = new File("C:\temp\sample3.bin");
OutputStream os = new BufferedOutputStream(new FileOutputStream(outputfile));
byte[] buffer2 = new byte[2];
zis.getNextEntry();
while(true) {
if(zis.read(buffer2) != -1) {
os.write(buffer2);
}
else break;
}
os.flush();
os.close();
zis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
我能够使用此图像产生错误(将其保存并压缩为 sample3.zip 和 运行 上的代码),但是任何足够大的二进制文件都应该显示差异。
您可以使用更逐字的方式来检查是否所有字节都已读取和写入,例如像
这样的方法 public int extract(ZipInputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE];
int total = 0;
int read;
while ((read = in.read(buffer)) != -1) {
total += read;
out.write(buffer, 0, read);
}
return total;
}
如果在write()
中没有使用read
参数,该方法假定buffer
的全部内容将被写出,这可能不正确,如果buffer
未满
OutputStream
可以在 extract()
方法内部或外部刷新和关闭。调用 close()
就足够了,因为它还调用了 flush()
.
无论如何,Java的"standard" I/O代码,和java.util.zip
包一样,已经过测试和广泛使用,所以它不太可能可能有一个如此根本的错误,以至于很容易导致字节丢失。
while (true) {
if(zis.read(buffer2) != -1) {
os.write(buffer2);
}
else break;
}
常见问题。你忽略了计数。应该是:
int count;
while ((count = zis.read(buffer2)) != -1)
{
os.write(buffer2, 0, count);
}
注意:
- 缓冲区大小为 2 是荒谬的。使用8192或更多。
flush()
在close()
之前是多余的。