java.util.zip解压问题 你用的是什么操作系统,我在win2000 pro 下一切正常啊。你把test.zip写成绝对路径看看,例如:c:/test.zip 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我用的是win2000 server,我觉得我写的程序也没什么问题;我估计和路径没什么关系可能,这个错误并不是找不到zip文件,是能找到文件的,关键就是getnextentry()这个方法执行有问题 test.zip里面的文件名是不是包含中文? 如果是中文的问题,你可以看看这篇文章,相信对你有帮助转帖自清华bbs有一些代码由于粘贴的格式不对,需要调整一下,不过很快就搞定。我已经测试过了,没问题发信人: zengcheng (我是曾诚), 信区: Java 标 题: 用ZipOutputStream压缩中文文件夹完全解决方案发信站: BBS 水木清华站 (Wed Apr 9 23:45:18 2003), 转信 用ZipOutputStream类压缩中文文件名的文件(夹)完全解决方案 在刚开始直接用ZipOutputStream类压缩文件的时候,英文文件名的文件是完全没有问题的,中文文件名就不行,表现在:1.如果是文件,那么文件名就成了乱码,而文件内容完好; 这很容易理解,因为ZipOutputStream对文件内容的处理和OutputStream完全一样,除了写的bytes是压缩过的bytes这一点除外.2.如果是文件夹,那就彻底糟了,不光文件夹的名字成了乱码,并且此文件夹下面的东西全部消失.以上两点说明:ZipOutputStream在设计的时候根本没有考虑文件名是中文的情况.于是想到改ZipOutputStream的源代码;用Cavaj反编译JAVA_HOME/jre/lib/rt.jar中的java.util.zip.ZipOutputStream类的源代码,发现对文件名的处理有这样两段代码,:line291: byte abyte0[] = getUTF8Bytes(zipentry.name);//在方法private void writeLOC(ZipEntry zipentry)中line322: byte abyte0[] = getUTF8Bytes(zipentry.name);//在方法private void writeCEN(ZipEntry zipentry)中注意:由于jdk或反编译工具的差异,具体的行数可能有差别不管这两个方法的具体作用,只看这两段代码在这两段代码中:zipentry.name是ZipEntry类的一个访问权限为缺省的String域.因为用ZipOutput-Stream压缩文件时,每个文件或文件夹都对应着一个ZipEntry,所有可以把zipentry.name看作是文件(夹)的名字.我们再看ZipOutputStream是怎么处理这个name的: byte abyte0[] = getUTF8Bytes(zipentry.name);可以看到,他把zipentry.name也就是我们关心的文件名用getUTF8Bytes(String s)这个方法处理了一下,然后返回一个byte型的数组给abyte0.查了一下源文件,getUTF8Bytes(String s)这个方法是个private方法,他将s中的每一个unicode字符转换为UTF-8的字节后返回一个字节数组.问题会不会出在这个转换上呢?于是,我试着将这两段代码改为:line291: byte abyte0[] = zipentry.name.getBytes("gb2312");line322: byte abyte0[] = zipentry.name.getBytes("gb2312");编译这段代码,然后将JAVA_HOME/jre/lib/rt.jar中的java.util.zip.ZipOutputStream-.class文件替换为新编译的文件(WinRar应该提供了直接更新压缩文件内的文件的方法,但本人很土,倒腾了半天也倒腾不出来,因此是先解压rt,jar,然后替换再压缩,很笨吧!),再试着用以前的代码压缩一个中文文件夹,用WinRar打开,成功了! 短暂的兴奋过后,又想到一个问题:如果要在另外一台机器上也实现这个功能,岂不又要改那台机器的rt.jar?这样弄是很麻烦的,或者说是不可行的.说白了,改jdk的源代码除了自己玩玩以外,还真没觉得有什么用.于是又想有没有其他的方法. 我想,既然改一个文件嫌麻烦,何不自己重新再做一个zip包,以后要用到压缩的时候用这个新的zip包就行了,不用java.util.zip包,就跟用bean一样,这样多方便! 于是我把zip包里面的所有.class文件反编译为.java文件(ZipOutputStream是改动后的),然后把文件头上的package语句改成"package xxx;","xxx"是我自己定义的包名.接下来全部编译,就生成了一个完全拷贝 java.util.zip包的新包,只有一点点不一样.接着,兴冲冲地把执行压缩的代码前面的"import java.util.zip*;"换成"import xxx;",心里还在想,java.util.zip,去死吧!结果一运行,给我一个打击:UnsatisfiedLinkError!查了一下jdk文档,这个error是在loadlibrary的时候抛出的,原来java.util.zip还用到了native方法,这下完蛋了:.class文件可以反编译,.dll我可搞不定.顺便问一句,谁能搞定.dll啊? 还不死心:ZipOutputStream并没有用到native方法,是别的类用到的,那我只把java.util.zip包里面的ZipOutputStream一个类放到新包里面,其他类不动不就行了吗?于是把xxx包里面的其它类都删掉,只留下一个ZipOutputstream,并且改名为ZipOutputStreamE,因为以后压缩文件的时候还是用到java.util.zip包,xxx包和java.util.zip包里面都有ZipOutputstream的话就要写全名,很麻烦.javac,发现又有大麻烦:麻烦1: public class ZipOutputStreamE extends DeflaterOutputStream implements ZipConstants这个ZipConstants是java.util.zip包的一个class,访问控制符为缺省,不是public,也就是说只有同一包的类才能访问,而现在ZipOutputStreamE已经是package xxx了;麻烦2: ZipOutputStreamE的代码大量访问到了ZipEntry类的一些属性,而这些属性的访问控制符都是缺省的,跟上面的情况一样,都是只有同一个包的类才能访问;大量脑细胞死亡后,麻烦被干掉:麻烦1的死: 反编译了ZipConstants,发现里面都是定义的一些常量,没有方法,于是把java.uti.zip包里面的ZipConstants类反编译,然后把文件头上的"package java.util.zip;"改为"package xxx;",编译后放到xxx里面,这下又成一家人了;麻烦2的死:虽然要用到的ZipEntry的属性都是缺省的,但是ZipEntry类提供了读写这些属性的public方法,比如ZipEntry有属性long time,对应着就有public long getTime()和public void setTime(long l),于是,需要涉及到time属性的地方就可以用这两个方法代替,比如:if(zipentry.time == -1L)可改为if(zipentry.getTime() == -1L) zipentry.time=System.currentTimeMillis(); 可改为zipentry.setTime(System.currentTimeMillis());但是有三个例外,这就是ZipEntry的int flag, int version和 long offset三个属性.ZipEntry没有提供这三个属性的读写方法,怎么办?我查了一下zip包的源代码,发现这三个属性用处不大,总共只在三个类里出现过:ZipEntry,ZipOutputStream和ZipInputStream,其中ZipEntry只是定义了这三个属性,并没有用到,说得明白点就是这三个属性对于ZipEntry来说没用,对zip包里面的其他类也没有用,因此,我在ZipOutputStreamE里面又定义了三个变量int flag, int version和 long offset,来代替zipentry.flag,zipentry.version和zipentry.offset.这次改动之后,彻底成功了. 附:相关源代码1.ZipOutputStreamE//这个没必要看得很明白,只要搞清楚和ZipOutputStream的区别 //以及为什么要这样改动就行了package xxx;import java.io.*;import java.util.*;import java.util.zip.*;// Referenced classes of package xxx:// DeflaterOutputStream, Deflater, CRC32, ZipException,// ZipEntry, ZipConstantspublic class ZipOutputStreamE extends DeflaterOutputStream implements ZipConstants{ private ZipEntry entry; private Vector entries; private Hashtable names; private CRC32 crc; private long written; private long locoff; private String comment; private int method; private boolean finished; private boolean closed; public static final int STORED = 0; public static final int DEFLATED = 8; public int flag;//代替zipentry中的flag public int version;//代替zipentry中的version public long offset;//代替zipentry中的offset private void ensureOpen() throws IOException { if(closed) { throw new IOException("Stream closed"); } else { return; } } public ZipOutputStreamE(OutputStream outputstream) { super(outputstream, new Deflater(-1, true)); entries = new Vector(); names = new Hashtable(); crc = new CRC32(); locoff = 0L; method = 8; closed = false; } public void setComment(String s) { if(s.length() > 65535) { throw new IllegalArgumentException("invalid ZIP file comment"); } else { comment = s; return; } } public void setMethod(int i) { if(i != 8 && i != 0) { throw new IllegalArgumentException("invalid compression method"); } else { method = i; return; } } public void setLevel(int i) { super.def.setLevel(i); } public void putNextEntry(ZipEntry zipentry) throws IOException { ensureOpen(); if(entry != null) { closeEntry(); } if(zipentry.getTime() == -1L) { zipentry.setTime(System.currentTimeMillis()); } if(zipentry.getMethod() == -1) { zipentry.setMethod(method); } switch(zipentry.getMethod()) { case 8: // '\b' if(zipentry.getSize() == -1L || zipentry.getCompressedSize() == -1L || zipentry.getCrc() == -1L) { flag = 8; } else if(zipentry.getSize() != -1L && zipentry.getCompressedSize() != -1L && zipentry.getCrc() != -1L) { flag = 0; } else { throw new ZipException("DEFLATED entry missing size, compressed size, or crc-32"); } version = 20; break; case 0: // '\0' if(zipentry.getSize() == -1L) { zipentry.setSize(zipentry.getCompressedSize()); } else if(zipentry.getCompressedSize() == -1L) { zipentry.setCompressedSize(zipentry.getSize()); } else if(zipentry.getSize() != zipentry.getCompressedSize()) { throw new ZipException("STORED entry where compressed != uncompressed size"); } if(zipentry.getSize() == -1L || zipentry.getCrc() == -1L) { throw new ZipException("STORED entry missing size, compressed size, or crc-32"); } version = 10; flag = 0; break; default: throw new ZipException("unsupported compression method"); } offset = written; writeLOC(zipentry); if(names.put(zipentry.getName(), zipentry) != null) { throw new ZipException("duplicate entry: " + zipentry.getName()); } else { entries.addElement(zipentry); entry = zipentry; return; } } public void closeEntry() throws IOException { ensureOpen(); ZipEntry zipentry = entry; if(zipentry != null) { switch(zipentry.getMethod()) { case 8: // '\b' super.def.finish(); for(; !super.def.finished(); deflate()) { } if((flag & 8) == 0) { if(zipentry.getSize() != (long)super.def.getTotalIn()) { throw new ZipException("invalid entry size (expected" + zipentry.getSize() + " but got " + super.def.getTotalIn() + " bytes)"); } if(zipentry.getCompressedSize() != (long)super.def.getTotalOut()) { throw new ZipException("invalid entry compressed size (expected " + zipentry.getCompressedSize() + " but got " + super.def.getTotalOut() + " bytes)"); } if(zipentry.getCrc() != crc.getValue()) { throw new ZipException("invalid entry CRC-32 (expected 0x" + Long.toHexString(zipentry.getCrc()) + " but got 0x" + Long.toHexString(crc.getValue()) + ")"); } } else { zipentry.setSize(super.def.getTotalIn()) ; zipentry.setCompressedSize(super.def.getTotalOut()) ; zipentry.setCrc(crc.getValue()) ; writeEXT(zipentry); } super.def.reset(); written += zipentry.getCompressedSize(); break; case 0: // '\0' if(zipentry.getSize() != written - locoff) { throw new ZipException("invalid entry size (expected " +zipentry.getSize() + " but got " + (written - locoff) + " bytes)"); } if(zipentry.getCrc() != crc.getValue()) { throw new ZipException("invalid entry crc-32 (expected 0x" + Long.toHexString(zipentry.getCrc()) + " but got 0x" + Long.toHexString(crc.getValue()) + ")"); } break; default: throw new InternalError("invalid compression method"); } crc.reset(); entry = null; } } public synchronized void write(byte abyte0[], int i, int j) throws IOException { ensureOpen(); if(i < 0 || i > abyte0.length || j < 0 || i + j > abyte0.length || i+ j < 0) { throw new IndexOutOfBoundsException(); } if(j == 0) { return; } if(entry == null) { throw new ZipException("no current ZIP entry"); } switch(entry.getMethod()) { case 8: // '\b' super.write(abyte0, i, j); break; case 0: // '\0' written += j; if(written - locoff > entry.getSize()) { throw new ZipException("attempt to write past end of STORED entry"); } super.out.write(abyte0, i, j); break; default: throw new InternalError("invalid compression method"); } crc.update(abyte0, i, j); } 开始是有中文,我想到可能是中文名字引起的,但改成非中文名字后,还是依然提示这个错误;你说在你机器上就可以正常运行,怎么在我这就不行?就是用这个zipinputstream不行,我用zipfile来解压缩就可以正常运行,真是要晕了 public void finish() throws IOException { ensureOpen(); if(finished) { return; } if(entry != null) { closeEntry(); } if(entries.size() < 1) { throw new ZipException("ZIP file must have at least one entry"); } long l = written; for(Enumeration enumeration = entries.elements(); enumeration.hasMoreElements(); writeCEN((ZipEntry)enumeration.nextElement())) { } writeEND(l, written - l); finished = true; } public void close() throws IOException { finish(); super.out.close(); closed = true; } private void writeLOC(ZipEntry zipentry) throws IOException { writeInt(0x4034b50L); writeShort(version); writeShort(flag); writeShort(zipentry.getMethod()); writeInt(zipentry.getTime()); if((flag & 8) == 8) { writeInt(0L); writeInt(0L); writeInt(0L); } else { writeInt(zipentry.getCrc()); writeInt(zipentry.getCompressedSize()); writeInt(zipentry.getSize()); } byte abyte0[] = zipentry.getName().getBytes("gb2312"); writeShort(abyte0.length); writeShort(zipentry.getExtra() != null ? zipentry.getExtra().length : 0); writeBytes(abyte0, 0, abyte0.length); if(zipentry.getExtra() != null) { writeBytes(zipentry.getExtra(), 0, zipentry.getExtra().length); } locoff = written; } private void writeEXT(ZipEntry zipentry) throws IOException { writeInt(0x8074b50L); writeInt(zipentry.getCrc()); writeInt(zipentry.getCompressedSize()); writeInt(zipentry.getSize()); } private void writeCEN(ZipEntry zipentry) throws IOException { writeInt(0x2014b50L); writeShort(version); writeShort(version); writeShort(flag); writeShort(zipentry.getMethod()); writeInt(zipentry.getTime()); writeInt(zipentry.getCrc()); writeInt(zipentry.getCompressedSize()); writeInt(zipentry.getSize()); byte abyte0[] = zipentry.getName().getBytes("gb2312"); writeShort(abyte0.length); writeShort(zipentry.getExtra() != null ? zipentry.getExtra().length : 0); byte abyte1[]; if(zipentry.getComment() != null) { abyte1 = getUTF8Bytes(zipentry.getComment()); writeShort(abyte1.length); } else { abyte1 = null; writeShort(0); } writeShort(0); writeShort(0); writeInt(0L); writeInt(offset); writeBytes(abyte0, 0, abyte0.length); if(zipentry.getExtra() != null) { writeBytes(zipentry.getExtra(), 0, zipentry.getExtra().length); } if(abyte1 != null) { writeBytes(abyte1, 0, abyte1.length); } } private void writeEND(long l, long l1) throws IOException { writeInt(0x6054b50L); writeShort(0); writeShort(0); writeShort(entries.size()); writeShort(entries.size()); writeInt(l1); writeInt(l); if(comment != null) { byte abyte0[] = getUTF8Bytes(comment); writeShort(abyte0.length); writeBytes(abyte0, 0, abyte0.length); } else { writeShort(0); } } private void writeShort(int i) throws IOException { OutputStream outputstream = super.out; outputstream.write(i >>> 0 & 0xff); outputstream.write(i >>> 8 & 0xff); written += 2L; } private void writeInt(long l) throws IOException { OutputStream outputstream = super.out; outputstream.write((int)(l >>> 0 & 255L)); outputstream.write((int)(l >>> 8 & 255L)); outputstream.write((int)(l >>> 16 & 255L)); outputstream.write((int)(l >>> 24 & 255L)); written += 4L; } private void writeBytes(byte abyte0[], int i, int j) throws IOException { super.out.write(abyte0, i, j); written += j; } private static byte[] getUTF8Bytes(String s) { char ac[] = s.toCharArray(); int i = ac.length; int j = 0; for(int k = 0; k < i; k++) { char c = ac[k]; if(c <= '\177') { j++; } else if(c <= '\u07FF') { j += 2; } else { j += 3; } } byte abyte0[] = new byte[j]; int l = 0; for(int i1 = 0; i1 < i; i1++) { char c1 = ac[i1]; if(c1 <= '\177') { abyte0[l++] = (byte)c1; } else if(c1 <= '\u07FF') { abyte0[l++] = (byte)(c1 >> 6 | 0xc0); abyte0[l++] = (byte)(c1 & 0x3f | 0x80); } else { abyte0[l++] = (byte)(c1 >> 12 | 0xe0); abyte0[l++] = (byte)(c1 >> 6 & 0x3f | 0x80); abyte0[l++] = (byte)(c1 & 0x3f | 0x80); } } return abyte0; }} 2.执行压缩的代码://这个就有必要看明白了package xxx;import java.io.*;import java.util.*;import java.util.zip.*;public class OperFile{FileOutputStream fos;CheckedOutputStream csum;ZipOutputStreamE out;//新定义的int index;public void zipFold(File unzipf,File zipf) throws Exception{//unzipf是待压缩的文件,zipf是压缩后的文件if(!unzipf.exists())return;else{fos=new FileOutputStream(zipf);csum=new CheckedOutputStream(fos,new Adler32());out=new ZipOutputStreamE(new BufferedOutputStream(csum));index=unzipf.toString().lastIndexOf("\\");zipF(unzipf);out.close();return;}} zipFold()定义完毕public void zipF(File f) throws Exception{if(f.isFile()){FileInputStream in=new FileInputStream(f);String etr=f.toString().substring(index+1);out.putNextEntry(new ZipEntry(etr));byte[] b=new byte[4096];int byte_read;while((byte_read=in.read(b))!=-1)out.write(b,0,byte_read);in.close();return;}else{ZipEntry ze=new ZipEntry(f.toString().substring(index+1)+"/");out.putNextEntry(ze);File[] fs=f.listFiles();if(fs!=null)for(int i=0;i<fs.length;i++)zipF(fs[i]);}}//zipF()定义完毕public static void main(String args[]){if(args.length!=2)System.exit();else{OperFile opf=new OperFile();opf.zipFold(new File(args[0]),new File(args[1]));}}}--※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.82.193] 靠,开始有中文,后来我只是把zip文件给修改了一下,但一直都是如此错误,刚才我把jbuilder给重新启动了一次,结果就ok了,看来是jbuilder的bug,谢谢两位! 多线程同步问题 菜鸟求助小问题...... Java 目录选择 (不要选择文件,而只是选择文件夹获取目录) 大家帮帮新手!一共80分,另两贴拿! 菜鸟 java.lang.NoClassDefFoundError 誰能幫我解決這個問題阿(附源碼) 100分急求win2000server+jrun4+mysql3.23 的合理中文解决方案 困扰我多时的问题,大家来帮忙 阿里邮箱发送失败 本公司招vfp程序员,懂java的优先 linux下JAVA串口编程
发信人: zengcheng (我是曾诚), 信区: Java
标 题: 用ZipOutputStream压缩中文文件夹完全解决方案
发信站: BBS 水木清华站 (Wed Apr 9 23:45:18 2003), 转信 用ZipOutputStream类压缩中文文件名的文件(夹)完全解决方案
在刚开始直接用ZipOutputStream类压缩文件的时候,英文文件名的文件是完全没
有问题的,中文文件名就不行,表现在:
1.如果是文件,那么文件名就成了乱码,而文件内容完好; 这很容易理解,因为
ZipOutputStream对文件内容的处理和OutputStream完全一样,除了写的bytes
是压缩过的bytes这一点除外.
2.如果是文件夹,那就彻底糟了,不光文件夹的名字成了乱码,并且此文件夹下面的
东西全部消失.
以上两点说明:ZipOutputStream在设计的时候根本没有考虑文件名是中文的情况.
于是想到改ZipOutputStream的源代码;
用Cavaj反编译JAVA_HOME/jre/lib/rt.jar中的java.util.zip.ZipOutputStream类的源
代码,发现对文件名的处理有这样两段代码,:
line291: byte abyte0[] = getUTF8Bytes(zipentry.name);
//在方法private void writeLOC(ZipEntry zipentry)中
line322: byte abyte0[] = getUTF8Bytes(zipentry.name);
//在方法private void writeCEN(ZipEntry zipentry)中
注意:由于jdk或反编译工具的差异,具体的行数可能有差别
不管这两个方法的具体作用,只看这两段代码
在这两段代码中:
zipentry.name是ZipEntry类的一个访问权限为缺省的String域.因为用ZipOutput-
Stream压缩文件时,每个文件或文件夹都对应着一个ZipEntry,所有可以把
zipentry.name看作是文件(夹)的名字.我们再看ZipOutputStream是怎么处理这个
name的:
byte abyte0[] = getUTF8Bytes(zipentry.name);
可以看到,他把zipentry.name也就是我们关心的文件名用getUTF8Bytes(String s)
这个方法处理了一下,然后返回一个byte型的数组给abyte0.查了一下源文件,
getUTF8Bytes(String s)这个方法是个private方法,他将s中的每一个unicode字符
转换为UTF-8的字节后返回一个字节数组.问题会不会出在这个转换上呢?
于是,我试着将这两段代码改为:
line291: byte abyte0[] = zipentry.name.getBytes("gb2312");
line322: byte abyte0[] = zipentry.name.getBytes("gb2312");
编译这段代码,然后将JAVA_HOME/jre/lib/rt.jar中的java.util.zip.ZipOutputStream
-.class文件替换为新编译的文件(WinRar应该提供了直接更新压缩文件内的文件的
方法,但本人很土,倒腾了半天也倒腾不出来,因此是先解压rt,jar,然后替换再压缩,
很笨吧!),再试着用以前的代码压缩一个中文文件夹,用WinRar打开,成功了!
短暂的兴奋过后,又想到一个问题:如果要在另外一台机器上也实现这个功能,岂不
又要改那台机器的rt.jar?这样弄是很麻烦的,或者说是不可行的.说白了,改jdk的源代
码除了自己玩玩以外,还真没觉得有什么用.于是又想有没有其他的方法.
我想,既然改一个文件嫌麻烦,何不自己重新再做一个zip包,以后要用到压缩的时候用
这个新的zip包就行了,不用java.util.zip包,就跟用bean一样,这样多方便!
于是我把zip包里面的所有.class文件反编译为.java文件(ZipOutputStream是改动
后的),然后把文件头上的package语句改成"package xxx;","xxx"是我自己定义的包名.
接下来全部编译,就生成了一个完全拷贝 java.util.zip包的新包,只有一点点不一样.接
着,兴冲冲地把执行压缩的代码前面的"import java.util.zip*;"换成"import xxx;",心
里还在想,java.util.zip,去死吧!结果一运行,给我一个打击:UnsatisfiedLinkError!
查了一下jdk文档,这个error是在loadlibrary的时候抛出的,原来java.util.zip还用到
了native方法,这下完蛋了:.class文件可以反编译,.dll我可搞不定.顺便问一句,谁能搞定
.dll啊?
还不死心:ZipOutputStream并没有用到native方法,是别的类用到的,那我只把
java.util.zip包里面的ZipOutputStream一个类放到新包里面,其他类不动不就行了吗?
于是把xxx包里面的其它类都删掉,只留下一个ZipOutputstream,并且改名为
ZipOutputStreamE,因为以后压缩文件的时候还是用到java.util.zip包,xxx包和java.
util.zip包里面都有ZipOutputstream的话就要写全名,很麻烦.
javac,发现又有大麻烦:
麻烦1: public class ZipOutputStreamE extends DeflaterOutputStream
implements ZipConstants
这个ZipConstants是java.util.zip包的一个class,访问控制符为缺省,不是public,也就
是说只有同一包的类才能访问,而现在ZipOutputStreamE已经是package xxx了;
麻烦2: ZipOutputStreamE的代码大量访问到了ZipEntry类的一些属性,而这些属性
的访问控制符都是缺省的,跟上面的情况一样,都是只有同一个包的类才能访问;
大量脑细胞死亡后,麻烦被干掉:
麻烦1的死: 反编译了ZipConstants,发现里面都是定义的一些常量,没有方法,于是把
java.uti.zip包里面的ZipConstants类反编译,然后把文件头上的"package java.util.
zip;"改为"package xxx;",编译后放到xxx里面,这下又成一家人了;
麻烦2的死:虽然要用到的ZipEntry的属性都是缺省的,但是ZipEntry类提供了读写这些
属性的public方法,比如ZipEntry有属性long time,对应着就有public long getTime()
和public void setTime(long l),于是,需要涉及到time属性的地方就可以用这两个方法
代替,比如:if(zipentry.time == -1L)可改为if(zipentry.getTime() == -1L)
zipentry.time=System.currentTimeMillis();
可改为zipentry.setTime(System.currentTimeMillis());
但是有三个例外,这就是ZipEntry的int flag, int version和 long offset三个属性.Z
ipEntry没有提供这三个属性的读写方法,怎么办?我查了一下zip包的源代码,发现这三个
属性用处不大,总共只在三个类里出现过:ZipEntry,ZipOutputStream和ZipInputStream,
其中ZipEntry
只是定义了这三个属性,并没有用到,说得明白点就是这三个属性对于ZipEntry来说没用
,对zip包里面的其他类也没有用,因此,我在ZipOutputStreamE里面又定义了三个变量
int flag, int version和 long offset,来代替zipentry.flag,zipentry.version和zi
pentry.offset.
这次改动之后,彻底成功了.
1.ZipOutputStreamE//这个没必要看得很明白,只要搞清楚和ZipOutputStream的区别
//以及为什么要这样改动就行了
package xxx;
import java.io.*;
import java.util.*;
import java.util.zip.*;
// Referenced classes of package xxx:
// DeflaterOutputStream, Deflater, CRC32, ZipException,
// ZipEntry, ZipConstants
public class ZipOutputStreamE extends DeflaterOutputStream
implements ZipConstants
{
private ZipEntry entry;
private Vector entries;
private Hashtable names;
private CRC32 crc;
private long written;
private long locoff;
private String comment;
private int method;
private boolean finished;
private boolean closed;
public static final int STORED = 0;
public static final int DEFLATED = 8;
public int flag;//代替zipentry中的flag
public int version;//代替zipentry中的version
public long offset;//代替zipentry中的offset
private void ensureOpen()
throws IOException
{
if(closed)
{
throw new IOException("Stream closed");
} else
{
return;
}
}
public ZipOutputStreamE(OutputStream outputstream)
{
super(outputstream, new Deflater(-1, true));
entries = new Vector();
names = new Hashtable();
crc = new CRC32();
locoff = 0L;
method = 8;
closed = false;
}
public void setComment(String s)
{
if(s.length() > 65535)
{
throw new IllegalArgumentException("invalid ZIP file comment");
} else
{
comment = s;
return;
}
}
public void setMethod(int i)
{
if(i != 8 && i != 0)
{
throw new IllegalArgumentException("invalid compression method")
;
} else
{
method = i;
return;
}
}
public void setLevel(int i)
{
super.def.setLevel(i);
}
public void putNextEntry(ZipEntry zipentry)
throws IOException
{
ensureOpen();
if(entry != null)
{
closeEntry();
}
if(zipentry.getTime() == -1L)
{
zipentry.setTime(System.currentTimeMillis());
}
if(zipentry.getMethod() == -1)
{
zipentry.setMethod(method);
}
switch(zipentry.getMethod())
{
case 8: // '\b'
if(zipentry.getSize() == -1L || zipentry.getCompressedSize() ==
-1L || zipentry.getCrc() == -1L)
{
flag = 8;
} else
if(zipentry.getSize() != -1L && zipentry.getCompressedSize() !=
-1L && zipentry.getCrc() != -1L)
{
flag = 0;
} else
{
throw new ZipException("DEFLATED entry missing size, compres
sed size, or crc-32");
}
version = 20;
break;
case 0: // '\0'
if(zipentry.getSize() == -1L)
{
zipentry.setSize(zipentry.getCompressedSize());
} else
if(zipentry.getCompressedSize() == -1L)
{
zipentry.setCompressedSize(zipentry.getSize());
} else
if(zipentry.getSize() != zipentry.getCompressedSize())
{
throw new ZipException("STORED entry where compressed != unc
ompressed size");
}
if(zipentry.getSize() == -1L || zipentry.getCrc() == -1L)
{
throw new ZipException("STORED entry missing size, compresse
d size, or crc-32");
}
version = 10;
flag = 0;
break;
default:
throw new ZipException("unsupported compression method");
}
offset = written;
writeLOC(zipentry);
if(names.put(zipentry.getName(), zipentry) != null)
{
throw new ZipException("duplicate entry: " + zipentry.getName())
;
} else
{
entries.addElement(zipentry);
entry = zipentry;
return;
}
}
public void closeEntry()
throws IOException
{
ensureOpen();
ZipEntry zipentry = entry;
if(zipentry != null)
{
switch(zipentry.getMethod())
{
case 8: // '\b'
super.def.finish();
for(; !super.def.finished(); deflate()) { }
if((flag & 8) == 0)
{
if(zipentry.getSize() != (long)super.def.getTotalIn())
{
throw new ZipException("invalid entry size (expected
" + zipentry.getSize() + " but got " + super.def.getTotalIn() + " bytes)"); }
if(zipentry.getCompressedSize() != (long)super.def.getTo
talOut())
{
throw new ZipException("invalid entry compressed siz
e (expected " + zipentry.getCompressedSize() + " but got " + super.def.getTo
talOut() + " bytes)");
}
if(zipentry.getCrc() != crc.getValue())
{
throw new ZipException("invalid entry CRC-32 (expect
ed 0x" + Long.toHexString(zipentry.getCrc()) + " but got 0x" + Long.toHexStr
ing(crc.getValue()) + ")");
}
} else
{
zipentry.setSize(super.def.getTotalIn()) ;
zipentry.setCompressedSize(super.def.getTotalOut()) ;
zipentry.setCrc(crc.getValue()) ;
writeEXT(zipentry);
}
super.def.reset();
written += zipentry.getCompressedSize();
break;
case 0: // '\0'
if(zipentry.getSize() != written - locoff)
{
throw new ZipException("invalid entry size (expected " +
zipentry.getSize() + " but got " + (written - locoff) + " bytes)");
}
if(zipentry.getCrc() != crc.getValue())
{
throw new ZipException("invalid entry crc-32 (expected 0
x" + Long.toHexString(zipentry.getCrc()) + " but got 0x" + Long.toHexString(
crc.getValue()) + ")");
}
break;
default:
throw new InternalError("invalid compression method");
}
crc.reset();
entry = null;
}
}
public synchronized void write(byte abyte0[], int i, int j)
throws IOException
{
ensureOpen();
if(i < 0 || i > abyte0.length || j < 0 || i + j > abyte0.length || i
+ j < 0)
{
throw new IndexOutOfBoundsException();
}
if(j == 0)
{
return;
}
if(entry == null)
{
throw new ZipException("no current ZIP entry");
}
switch(entry.getMethod())
{
case 8: // '\b'
super.write(abyte0, i, j);
break;
case 0: // '\0'
written += j;
if(written - locoff > entry.getSize())
{
throw new ZipException("attempt to write past end of STORED
entry");
}
super.out.write(abyte0, i, j);
break;
default:
throw new InternalError("invalid compression method");
}
crc.update(abyte0, i, j);
}
throws IOException
{
ensureOpen();
if(finished)
{
return;
}
if(entry != null)
{
closeEntry();
}
if(entries.size() < 1)
{
throw new ZipException("ZIP file must have at least one entry"); }
long l = written;
for(Enumeration enumeration = entries.elements(); enumeration.hasMor
eElements(); writeCEN((ZipEntry)enumeration.nextElement())) { }
writeEND(l, written - l);
finished = true;
}
public void close()
throws IOException
{
finish();
super.out.close();
closed = true;
}
private void writeLOC(ZipEntry zipentry)
throws IOException
{
writeInt(0x4034b50L);
writeShort(version);
writeShort(flag);
writeShort(zipentry.getMethod());
writeInt(zipentry.getTime());
if((flag & 8) == 8)
{
writeInt(0L);
writeInt(0L);
writeInt(0L);
} else
{
writeInt(zipentry.getCrc());
writeInt(zipentry.getCompressedSize());
writeInt(zipentry.getSize());
}
byte abyte0[] = zipentry.getName().getBytes("gb2312");
writeShort(abyte0.length);
writeShort(zipentry.getExtra() != null ? zipentry.getExtra().length
: 0);
writeBytes(abyte0, 0, abyte0.length);
if(zipentry.getExtra() != null)
{
writeBytes(zipentry.getExtra(), 0, zipentry.getExtra().length);
}
locoff = written;
}
private void writeEXT(ZipEntry zipentry)
throws IOException
{
writeInt(0x8074b50L);
writeInt(zipentry.getCrc());
writeInt(zipentry.getCompressedSize());
writeInt(zipentry.getSize());
}
private void writeCEN(ZipEntry zipentry)
throws IOException
{
writeInt(0x2014b50L);
writeShort(version);
writeShort(version);
writeShort(flag);
writeShort(zipentry.getMethod());
writeInt(zipentry.getTime());
writeInt(zipentry.getCrc());
writeInt(zipentry.getCompressedSize());
writeInt(zipentry.getSize());
byte abyte0[] = zipentry.getName().getBytes("gb2312");
writeShort(abyte0.length);
writeShort(zipentry.getExtra() != null ? zipentry.getExtra().length
: 0);
byte abyte1[];
if(zipentry.getComment() != null)
{
abyte1 = getUTF8Bytes(zipentry.getComment());
writeShort(abyte1.length);
} else
{
abyte1 = null;
writeShort(0);
}
writeShort(0);
writeShort(0);
writeInt(0L);
writeInt(offset);
writeBytes(abyte0, 0, abyte0.length);
if(zipentry.getExtra() != null)
{
writeBytes(zipentry.getExtra(), 0, zipentry.getExtra().length);
}
if(abyte1 != null)
{
writeBytes(abyte1, 0, abyte1.length);
}
}
private void writeEND(long l, long l1)
throws IOException
{
writeInt(0x6054b50L);
writeShort(0);
writeShort(0);
writeShort(entries.size());
writeShort(entries.size());
writeInt(l1);
writeInt(l);
if(comment != null)
{
byte abyte0[] = getUTF8Bytes(comment);
writeShort(abyte0.length);
writeBytes(abyte0, 0, abyte0.length);
} else
{
writeShort(0);
}
}
private void writeShort(int i)
throws IOException
{
OutputStream outputstream = super.out;
outputstream.write(i >>> 0 & 0xff);
outputstream.write(i >>> 8 & 0xff);
written += 2L;
}
private void writeInt(long l)
throws IOException
{
OutputStream outputstream = super.out;
outputstream.write((int)(l >>> 0 & 255L));
outputstream.write((int)(l >>> 8 & 255L));
outputstream.write((int)(l >>> 16 & 255L));
outputstream.write((int)(l >>> 24 & 255L));
written += 4L;
}
private void writeBytes(byte abyte0[], int i, int j)
throws IOException
{
super.out.write(abyte0, i, j);
written += j;
}
private static byte[] getUTF8Bytes(String s)
{
char ac[] = s.toCharArray();
int i = ac.length;
int j = 0;
for(int k = 0; k < i; k++)
{
char c = ac[k];
if(c <= '\177')
{
j++;
} else
if(c <= '\u07FF')
{
j += 2;
} else
{
j += 3;
}
}
byte abyte0[] = new byte[j];
int l = 0;
for(int i1 = 0; i1 < i; i1++)
{
char c1 = ac[i1];
if(c1 <= '\177')
{
abyte0[l++] = (byte)c1;
} else
if(c1 <= '\u07FF')
{
abyte0[l++] = (byte)(c1 >> 6 | 0xc0);
abyte0[l++] = (byte)(c1 & 0x3f | 0x80);
} else
{
abyte0[l++] = (byte)(c1 >> 12 | 0xe0);
abyte0[l++] = (byte)(c1 >> 6 & 0x3f | 0x80);
abyte0[l++] = (byte)(c1 & 0x3f | 0x80);
}
}
return abyte0;
}
}
package xxx;
import java.io.*;
import java.util.*;
import java.util.zip.*;
public class OperFile{
FileOutputStream fos;
CheckedOutputStream csum;
ZipOutputStreamE out;//新定义的
int index;
public void zipFold(File unzipf,File zipf) throws Exception{//unzipf是待压缩
的文件,zipf是压缩后的文件
if(!unzipf.exists())
return;
else{
fos=new FileOutputStream(zipf);
csum=new CheckedOutputStream(fos,new Adler32());
out=new ZipOutputStreamE(new BufferedOutputStream(csum));
index=unzipf.toString().lastIndexOf("\\");
zipF(unzipf);
out.close();
return;
}
} zipFold()定义完毕
public void zipF(File f) throws Exception{
if(f.isFile()){
FileInputStream in=new FileInputStream(f);
String etr=f.toString().substring(index+1);
out.putNextEntry(new ZipEntry(etr));
byte[] b=new byte[4096];
int byte_read;
while((byte_read=in.read(b))!=-1)
out.write(b,0,byte_read);
in.close();
return;
}
else{
ZipEntry ze=new ZipEntry(f.toString().substring(index+1)+"/");
out.putNextEntry(ze);
File[] fs=f.listFiles();
if(fs!=null)
for(int i=0;i<fs.length;i++)
zipF(fs[i]);
}
}//zipF()定义完毕public static void main(String args[]){
if(args.length!=2)
System.exit();
else{
OperFile opf=new OperFile();
opf.zipFold(new File(args[0]),new File(args[1]));
}
}
}--※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.82.193]