在对《java编程思想v3》的例子程序时,发现一个程序上的小bug。问题发生在第十二章——java的IO系统的ZipCompress 这个程序上。下面让我们先看看这个程序发生错误的地方是什么样子:
FileOutputStream f = new FileOutputStream("test.zip");
CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32());
ZipOutputStream zos = new ZipOutputStream(csum);
BufferedOutputStream out = new BufferedOutputStream(zos);
//给zip文件添加注释
zos.setComment("A test of Java Zipping");
// No corresponding getComment(), though.
for(int i = 0; i < args.length; i++) {
System.out.println("Writing file " + args[i]);
BufferedReader in = new BufferedReader(new FileReader(args[i]));
zos.putNextEntry(new ZipEntry(args[i]));
int c;
while((c = in.read()) != -1)
out.write(c);
in.close();
}
out.close();
上面一段程序的意思就是:通过String[] args参数找到要压缩的文件,然后将他们一起压缩成一个名字叫test.zip的压缩包。根据程序的思路,我自己造了三个文本文件,分别是1.txt、2.txt、3.txt,内容分别是“1111”,“2222”,“3333”,然后执行程序,打开生成的test.zip,发现压缩包内的确是3个文件,但是打开每个文件,却发现1.txt和2.txt的内容都为空,3.txt的内容却是“111122223333”,三个文件的内容都写到了3.txt上。
再仔细看看程序,发现ZipOutputStream的外层包了个BufferedOutputStream,我隐隐觉得问题可能出在这里,于是我打开jdk文档,找到了对BufferedOutputStream的默认构造函数的解释:”Creates a new buffered output stream to write data to the specified underlying output stream with a default 512-byte buffer size“。看到这句话,我才恍然大悟了。“1.txt”,“2.txt”,“3.txt”三个文件总共12个byte大,虽然表面上我用out.write(c)将从三个文件读取的数据写到test.zip中,但是数据并没有真正的存到磁盘上,而是留在了BufferedOutputStream那默认的512byte的缓存中,直到我out.close()关闭输出流的时候,程序才把缓存中的数据真正的写到磁盘上。
原因已经弄清楚了,解决方法就是,在把每个文件数据写到test.zip后,将缓存清空:
for(int i = 0; i < args.length; i++) {
System.out.println("Writing file " + args[i]);
BufferedReader in = new BufferedReader(new FileReader(args[i]));
zos.putNextEntry(new ZipEntry(args[i]));
int c;
while((c = in.read()) != -1)
out.write(c);
out.flush();
in.close();
}
out.close();
// Checksum valid only after the file has been closed!
System.out.println("Checksum: " + csum.getChecksum().getValue());
再重新执行程序,打开test.zip,一切ok。写这篇文章,只是想将我自己的经验与大家分享,希望大家不要重蹈我的覆辙。
FileOutputStream f = new FileOutputStream("test.zip");
CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32());
ZipOutputStream zos = new ZipOutputStream(csum);
BufferedOutputStream out = new BufferedOutputStream(zos);
//给zip文件添加注释
zos.setComment("A test of Java Zipping");
// No corresponding getComment(), though.
for(int i = 0; i < args.length; i++) {
System.out.println("Writing file " + args[i]);
BufferedReader in = new BufferedReader(new FileReader(args[i]));
zos.putNextEntry(new ZipEntry(args[i]));
int c;
while((c = in.read()) != -1)
out.write(c);
in.close();
}
out.close();
for(int i = 0; i < args.length; i++) {
System.out.println("Writing file " + args[i]);
BufferedReader in = new BufferedReader(new FileReader(args[i]));
zos.putNextEntry(new ZipEntry(args[i]));
int c;
while((c = in.read()) != -1)
out.write(c);
out.flush();
in.close();
}
out.close();
// Checksum valid only after the file has been closed!
System.out.println("Checksum: " + csum.getChecksum().getValue());
本文介绍了一个关于Java Zip压缩的小Bug,即多个文件被错误地压缩为一个文件的问题,并提供了详细的解决方案。


被折叠的 条评论
为什么被折叠?



