Java ZipInputStream提取错误
下面是从只包含单个文件的zip文件中提取文件的一些代码。但是,提取的文件与通过WinZip或其他zip实用程序提取的相同文件不匹配。如果文件包含奇数个字节(因为我的缓冲区大小为2,一旦读取失败,我就会中止),我预计它可能会关闭一个字节。但是,在分析(使用WinMerge或Diff)使用下面的代码提取的文件与通过Winzip提取的文件时,Java提取中有几个区域缺少字节。有人知道我为什么或如何解决这个问题吗Java ZipInputStream提取错误,java,inputstream,zipinputstream,Java,Inputstream,Zipinputstream,下面是从只包含单个文件的zip文件中提取文件的一些代码。但是,提取的文件与通过WinZip或其他zip实用程序提取的相同文件不匹配。如果文件包含奇数个字节(因为我的缓冲区大小为2,一旦读取失败,我就会中止),我预计它可能会关闭一个字节。但是,在分析(使用WinMerge或Diff)使用下面的代码提取的文件与通过Winzip提取的文件时,Java提取中有几个区域缺少字节。有人知道我为什么或如何解决这个问题吗 package zipinputtest; import java.io.Buffere
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();
}
}
}
我能够使用此图像生成错误(将其和zip另存为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
参数,则该方法假定如果缓冲区未完全填满,则将写出缓冲区的全部内容,这可能是不正确的
OutputStream
可以在extract()
方法内部或外部刷新和关闭。调用close()
就足够了,因为它还调用flush()
在任何情况下,Java的“标准”I/O代码,如Java.util.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;
}
while (true) {
if(zis.read(buffer2) != -1) {
os.write(buffer2);
}
else break;
}
如果在write()
中未使用read
参数,则该方法假定如果缓冲区未完全填满,则将写出缓冲区的全部内容,这可能是不正确的
OutputStream
可以在extract()
方法内部或外部刷新和关闭。调用close()
就足够了,因为它还调用flush()
在任何情况下,Java的“标准”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()
是多余的
常见问题。你忽略了计数。应该是:
int count;
while ((count = zis.read(buffer2)) != -1)
{
os.write(buffer2, 0, count);
}
注意:
缓冲区大小为2是荒谬的。使用8192或更多
flush()
之前的close()
是多余的
OP, Read 实际上告诉你有多少字节已经是Read,所以他可以用它来检查文件大小。你知道C++中的CULL()是否也调用了FLUSER()的调用?如果是这样,我将停止使用Flash作为C++,而java是我使用的唯一语言。我希望C++中任何一个现代的实现都可以调用C++中的FLUSE.@ PTENUMPRO200,其中<代码>关闭()/<代码>。Java的FilterInputStream.close()
调用flush()
,因为可能存在应用程序端缓冲区。在关闭之前,任何I/O库都不应该刷新任何应用程序缓存,但我对C++ I/O库的耐心和兴趣是严格限制的。我在考虑STD::OFFROW,我检查了,结果是,CeleIE()调用了FrHuSE()。所以我想我不需要再调用flush()。这基本上是公共厕所的协议…当你完成后,不要冲厕所,只要关上门…很容易记住。开玩笑。。。OP, Read 实际上告诉你有多少字节已经是Read,所以他可以用它来检查文件大小。你知道C++中的CULL()是否也调用了FLUSER()的调用?如果是这样,我将停止使用Flash作为C++,而java是我使用的唯一语言。我希望C++中任何一个现代的实现都可以调用C++中的FLUSE.@ PTENUMPRO200,其中<代码>关闭()/<代码>。Java的FilterInputStream.close()
调用flush()
,因为可能存在应用程序端缓冲区。在关闭之前,任何I/O库都不应该刷新任何应用程序缓存,但我对C++ I/O库的耐心和兴趣是严格限制的。我在考虑STD::OFFROW,我检查了,结果是,CeleIE()调用了FrHuSE()。所以我想我不需要再调用flush()。这基本上是公共厕所的协议…当你完成后,不要冲厕所,只要关上门…很容易记住。开玩笑。。。我使用缓冲区大小2来演示这个问题。无法产生缓冲区大小为1的差异。完整版本的代码也将被设置为提取.zip中的所有文件,而不是仅提取1个文件。尽量使问题小而简洁。谢谢EJP和PNS。我今天大部分时间都在试着调试这个问题。你们俩为我节省了更多的调试时间。我唯一的问题是,为什么缓冲区不会被完全填满,除非它是文件的最后一次读取?不管怎样,我都会用柜台,只是好奇而已。为什么会有人坐呢?InputStream.read()
的契约不需要它。这就是它返回计数的原因。考虑一个套接字:在套接字接收缓冲区中得到了任何内容。考虑Zip:你可以得到任何可以解压缩的东西:但是协议是可行的,下一个解压缩块可能不适合当前的缓冲区。这是有道理的。ZipInputStream从FileInputStream接收数据块。尽管在除最后一种情况外的所有情况下,FileInputStream都有更多的数据要发送,但由于某些原因,它不会每次都填满缓冲区。我在想,为了提高效率,总是填满缓冲区是有意义的