在对《java编程思想v3》的例子程序时,发现一个程序上的小bug。问题发生在第十二章——java的IO系统的ZipCompress 这个程序上。下面让我们先看看这个程序发生错误的地方是什么样子:
上面一段程序的意思就是:通过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后,将缓存清空:
再重新执行程序,打开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());