本文使用了jdk1.5.0_13的源代碼。(java.uti.zip*)
實現方法:首先將java.uti.zip中的源代碼解壓出來。找到DeflaterOutputStream、InflaterInputStream、ZipConstants、ZipEntry、ZipInputStream、ZipOutputStream,放到新的包com.work.util.zip中,重新組織這些文件的import,能使用當前包中類的就使用當前包中的類。
重點要修改的類:ZipEntry,修改內容如下:
- //修改對應的程序,在這裏加載zip庫
- static{
- /*loadtheziplibrary*/
- java.security.AccessController
- .doPrivileged(newsun.security.action.LoadLibraryAction("zip"));
- //initIDs();
- }
- //static{
- ///*ZiplibraryisloadedfromSystem.initializeSystemClass*/
- //initIDs();
- //}
- //privatestaticnativevoidinitIDs();
其次修改ZipInputStream,大約在279行。
- //ZipEntrye=createZipEntry(getUTF8String(b,0,len));
- ZipEntrye=null;
- try{
- if(this.encoding.toUpperCase().equals("UTF-8"))
- e=createZipEntry(getUTF8String(b,0,len));
- else
- e=createZipEntry(newString(b,0,len,this.encoding));
- }catch(ExceptionbyteE){
- e=createZipEntry(getUTF8String(b,0,len));
- }
- //增加構造方法
- private String encoding = "UTF-8";
- public ZipInputStream(InputStream in, String encoding) {
super(new PushbackInputStream(in, 512), new Inflater(true), 512);
usesDefaultInflater = true;
if (in == null) {
throw new NullPointerException("in is null");
}
this.encoding = encoding;
}
再次修改ZipOutputStream類,源代碼如下:
- /*
- *@(#)ZipOutputStream.java1.3103/12/19
- *
- *Copyright2004SunMicrosystems,Inc.Allrightsreserved.
- *SUNPROPRIETARY/CONFIDENTIAL.Useissubjecttolicenseterms.
- */
- packagecom.work.util.zip;
- importjava.io.IOException;
- importjava.io.OutputStream;
- importjava.util.Enumeration;
- importjava.util.Hashtable;
- importjava.util.Vector;
- importjava.util.zip.CRC32;
- importjava.util.zip.Deflater;
- importjava.util.zip.ZipException;
- /**
- *ThisclassimplementsanoutputstreamfilterforwritingfilesintheZIP
- *fileformat.Includessupportforbothcompressedanduncompressedentries.
- *
- *@authorDavidConnelly
- *@version1.31,12/19/03
- */
- publicclassZipOutputStreamextendsDeflaterOutputStreamimplements
- ZipConstants{
- privateZipEntryentry;
- privateVectorentries=newVector();
- privateHashtablenames=newHashtable();
- privateCRC32crc=newCRC32();
- privatelongwritten=0;
- privatelonglocoff=0;
- privateStringcomment;
- privateintmethod=DEFLATED;
- privatebooleanfinished;
- privatebooleanclosed=false;
- /**
- *Checktomakesurethatthisstreamhasnotbeenclosed
- */
- privatevoidensureOpen()throwsIOException{
- if(closed){
- thrownewIOException("Streamclosed");
- }
- }
- /**
- *Compressionmethodforuncompressed(STORED)entries.
- */
- publicstaticfinalintSTORED=ZipEntry.STORED;
- /**
- *Compressionmethodforcompressed(DEFLATED)entries.
- */
- publicstaticfinalintDEFLATED=ZipEntry.DEFLATED;
- privateStringencoding="UTF-8";
- publicZipOutputStream(OutputStreamout,Stringencoding){
- super(out,newDeflater(Deflater.DEFAULT_COMPRESSION,true));
- usesDefaultDeflater=true;
- this.encoding=encoding;
- }
- /**
- *CreatesanewZIPoutputstream.
- *
- *@paramout
- *theactualoutputstream
- */
- publicZipOutputStream(OutputStreamout){
- super(out,newDeflater(Deflater.DEFAULT_COMPRESSION,true));
- usesDefaultDeflater=true;
- }
- /**
- *SetstheZIPfilecomment.
- *
- *@paramcomment
- *thecommentstring
- *@exceptionIllegalArgumentException
- *ifthelengthofthespecifiedZIPfilecommentisgreater
- *than0xFFFFbytes
- */
- publicvoidsetComment(Stringcomment){
- if(comment!=null&&comment.length()>0xffff/3
- &&getUTF8Length(comment)>0xffff){
- thrownewIllegalArgumentException("ZIPfilecommenttoolong.");
- }
- this.comment=comment;
- }
- /**
- *Setsthedefaultcompressionmethodforsubsequententries.Thisdefault
- *willbeusedwheneverthecompressionmethodisnotspecifiedforan
- *individualZIPfileentry,andisinitiallysettoDEFLATED.
- *
- *@parammethod
- *thedefaultcompressionmethod
- *@exceptionIllegalArgumentException
- *ifthespecifiedcompressionmethodisinvalid
- */
- publicvoidsetMethod(intmethod){
- if(method!=DEFLATED&&method!=STORED){
- thrownewIllegalArgumentException("invalidcompressionmethod");
- }
- this.method=method;
- }
- /**
- *SetsthecompressionlevelforsubsequententrieswhichareDEFLATED.The
- *defaultsettingisDEFAULT_COMPRESSION.
- *
- *@paramlevel
- *thecompressionlevel(0-9)
- *@exceptionIllegalArgumentException
- *ifthecompressionlevelisinvalid
- */
- publicvoidsetLevel(intlevel){
- def.setLevel(level);
- }
- /**
- *BeginswritinganewZIPfileentryandpositionsthestreamtothestart
- *oftheentrydata.Closesthecurrententryifstillactive.Thedefault
- *compressionmethodwillbeusedifnocompressionmethodwasspecified
- *fortheentry,andthecurrenttimewillbeusediftheentryhasnoset
- *modificationtime.
- *
- *@parame
- *theZIPentrytobewritten
- *@exceptionZipException
- *ifaZIPformaterrorhasoccurred
- *@exceptionIOException
- *ifanI/Oerrorhasoccurred
- */
- publicvoidputNextEntry(ZipEntrye)throwsIOException{
- ensureOpen();
- if(entry!=null){
- closeEntry();//closepreviousentry
- }
- if(e.time==-1){
- e.setTime(System.currentTimeMillis());
- }
- if(e.method==-1){
- e.method=method;//usedefaultmethod
- }
- switch(e.method){
- caseDEFLATED:
- if(e.size==-1||e.csize==-1||e.crc==-1){
- //storesize,compressedsize,andcrc-32indatadescriptor
- //immediatelyfollowingthecompressedentrydata
- e.flag=8;
- }elseif(e.size!=-1&&e.csize!=-1&&e.crc!=-1){
- //storesize,compressedsize,andcrc-32inLOCheader
- e.flag=0;
- }else{
- thrownewZipException(
- "DEFLATEDentrymissingsize,compressedsize,orcrc-32");
- }
- e.version=20;
- break;
- caseSTORED:
- //compressedsize,uncompressedsize,andcrc-32mustallbe
- //setforentriesusingSTOREDcompressionmethod
- if(e.size==-1){
- e.size=e.csize;
- }elseif(e.csize==-1){
- e.csize=e.size;
- }elseif(e.size!=e.csize){
- thrownewZipException(
- "STOREDentrywherecompressed!=uncompressedsize");
- }
- if(e.size==-1||e.crc==-1){
- thrownewZipException(
- "STOREDentrymissingsize,compressedsize,orcrc-32");
- }
- e.version=10;
- e.flag=0;
- break;
- default:
- thrownewZipException("unsupportedcompressionmethod");
- }
- e.offset=written;
- if(names.put(e.name,e)!=null){
- thrownewZipException("duplicateentry:"+e.name);
- }
- writeLOC(e);
- entries.addElement(e);
- entry=e;
- }
- /**
- *ClosesthecurrentZIPentryandpositionsthestreamforwritingthe
- *nextentry.
- *
- *@exceptionZipException
- *ifaZIPformaterrorhasoccurred
- *@exceptionIOException
- *ifanI/Oerrorhasoccurred
- */
- publicvoidcloseEntry()throwsIOException{
- ensureOpen();
- ZipEntrye=entry;
- if(e!=null){
- switch(e.method){
- caseDEFLATED:
- def.finish();
- while(!def.finished()){
- deflate();
- }
- if((e.flag&8)==0){
- //verifysize,compressedsize,andcrc-32settings
- if(e.size!=def.getBytesRead()){
- thrownewZipException("invalidentrysize(expected"
- +e.size+"butgot"+def.getBytesRead()
- +"bytes)");
- }
- if(e.csize!=def.getBytesWritten()){
- thrownewZipException(
- "invalidentrycompressedsize(expected"
- +e.csize+"butgot"
- +def.getBytesWritten()+"bytes)");
- }
- if(e.crc!=crc.getValue()){
- thrownewZipException(
- "invalidentryCRC-32(expected0x"
- +Long.toHexString(e.crc)
- +"butgot0x"
- +Long.toHexString(crc.getValue())
- +")");
- }
- }else{
- e.size=def.getBytesRead();
- e.csize=def.getBytesWritten();
- e.crc=crc.getValue();
- writeEXT(e);
- }
- def.reset();
- written+=e.csize;
- break;
- caseSTORED:
- //wealreadyknowthatbothe.sizeande.csizearethesame
- if(e.size!=written-locoff){
- thrownewZipException("invalidentrysize(expected"
- +e.size+"butgot"+(written-locoff)
- +"bytes)");
- }
- if(e.crc!=crc.getValue()){
- thrownewZipException("invalidentrycrc-32(expected0x"
- +Long.toHexString(e.crc)+"butgot0x"
- +Long.toHexString(crc.getValue())+")");
- }
- break;
- default:
- thrownewInternalError("invalidcompressionmethod");
- }
- crc.reset();
- entry=null;
- }
- }
- /**
- *WritesanarrayofbytestothecurrentZIPentrydata.Thismethodwill
- *blockuntilallthebytesarewritten.
- *
- *@paramb
- *thedatatobewritten
- *@paramoff
- *thestartoffsetinthedata
- *@paramlen
- *thenumberofbytesthatarewritten
- *@exceptionZipException
- *ifaZIPfileerrorhasoccurred
- *@exceptionIOException
- *ifanI/Oerrorhasoccurred
- */
- publicsynchronizedvoidwrite(byte[]b,intoff,intlen)
- throwsIOException{
- ensureOpen();
- if(off<0||len<0||off>b.length-len){
- thrownewIndexOutOfBoundsException();
- }elseif(len==0){
- return;
- }
- if(entry==null){
- thrownewZipException("nocurrentZIPentry");
- }
- switch(entry.method){
- caseDEFLATED:
- super.write(b,off,len);
- break;
- caseSTORED:
- written+=len;
- if(written-locoff>entry.size){
- thrownewZipException(
- "attempttowritepastendofSTOREDentry");
- }
- out.write(b,off,len);
- break;
- default:
- thrownewInternalError("invalidcompressionmethod");
- }
- crc.update(b,off,len);
- }
- /**
- *FinisheswritingthecontentsoftheZIPoutputstreamwithoutclosing
- *theunderlyingstream.Usethismethodwhenapplyingmultiplefiltersin
- *successiontothesameoutputstream.
- *
- *@exceptionZipException
- *ifaZIPfileerrorhasoccurred
- *@exceptionIOException
- *ifanI/Oexceptionhasoccurred
- */
- publicvoidfinish()throwsIOException{
- ensureOpen();
- if(finished){
- return;
- }
- if(entry!=null){
- closeEntry();
- }
- if(entries.size()<1){
- thrownewZipException("ZIPfilemusthaveatleastoneentry");
- }
- //writecentraldirectory
- longoff=written;
- Enumeratione=entries.elements();
- while(e.hasMoreElements()){
- writeCEN((ZipEntry)e.nextElement());
- }
- writeEND(off,written-off);
- finished=true;
- }
- /**
- *ClosestheZIPoutputstreamaswellasthestreambeingfiltered.
- *
- *@exceptionZipException
- *ifaZIPfileerrorhasoccurred
- *@exceptionIOException
- *ifanI/Oerrorhasoccurred
- */
- publicvoidclose()throwsIOException{
- if(!closed){
- super.close();
- closed=true;
- }
- }
- /*
- *Writeslocalfile(LOC)headerforspecifiedentry.
- */
- privatevoidwriteLOC(ZipEntrye)throwsIOException{
- writeInt(LOCSIG);//LOCheadersignature
- writeShort(e.version);//versionneededtoextract
- writeShort(e.flag);//generalpurposebitflag
- writeShort(e.method);//compressionmethod
- writeInt(e.time);//lastmodificationtime
- if((e.flag&8)==8){
- //storesize,uncompressedsize,andcrc-32indatadescriptor
- //immediatelyfollowingcompressedentrydata
- writeInt(0);
- writeInt(0);
- writeInt(0);
- }else{
- writeInt(e.crc);//crc-32
- writeInt(e.csize);//compressedsize
- writeInt(e.size);//uncompressedsize
- }
- //byte[]nameBytes=getUTF8Bytes(e.name);
- byte[]nameBytes=null;
- try{
- if(this.encoding.toUpperCase().equals("UTF-8"))
- nameBytes=getUTF8Bytes(e.name);
- else
- nameBytes=e.name.getBytes(this.encoding);
- }catch(ExceptionbyteE){
- nameBytes=getUTF8Bytes(e.name);
- }
- writeShort(nameBytes.length);
- writeShort(e.extra!=null?e.extra.length:0);
- writeBytes(nameBytes,0,nameBytes.length);
- if(e.extra!=null){
- writeBytes(e.extra,0,e.extra.length);
- }
- locoff=written;
- }
- /*
- *Writesextradatadescriptor(EXT)forspecifiedentry.
- */
- privatevoidwriteEXT(ZipEntrye)throwsIOException{
- writeInt(EXTSIG);//EXTheadersignature
- writeInt(e.crc);//crc-32
- writeInt(e.csize);//compressedsize
- writeInt(e.size);//uncompressedsize
- }
- /*
- *Writecentraldirectory(CEN)headerforspecifiedentry.REMIND:add
- *supportforfileattributes
- */
- privatevoidwriteCEN(ZipEntrye)throwsIOException{
- writeInt(CENSIG);//CENheadersignature
- writeShort(e.version);//versionmadeby
- writeShort(e.version);//versionneededtoextract
- writeShort(e.flag);//generalpurposebitflag
- writeShort(e.method);//compressionmethod
- writeInt(e.time);//lastmodificationtime
- writeInt(e.crc);//crc-32
- writeInt(e.csize);//compressedsize
- writeInt(e.size);//uncompressedsize
- //byte[]nameBytes=getUTF8Bytes(e.name);
- byte[]nameBytes=null;
- try{
- if(this.encoding.toUpperCase().equals("UTF-8"))
- nameBytes=getUTF8Bytes(e.name);
- else
- nameBytes=e.name.getBytes(this.encoding);
- }catch(ExceptionbyteE){
- nameBytes=getUTF8Bytes(e.name);
- }
- writeShort(nameBytes.length);
- writeShort(e.extra!=null?e.extra.length:0);
- byte[]commentBytes;
- if(e.comment!=null){
- //commentBytes=getUTF8Bytes(e.comment);
- try{
- if(this.encoding.toUpperCase().equals("UTF-8"))
- commentBytes=getUTF8Bytes(e.comment);
- else
- commentBytes=e.comment.getBytes(this.encoding);
- }catch(ExceptionbyteE){
- commentBytes=getUTF8Bytes(e.comment);
- }
- writeShort(commentBytes.length);
- }else{
- commentBytes=null;
- writeShort(0);
- }
- writeShort(0);//startingdisknumber
- writeShort(0);//internalfileattributes(unused)
- writeInt(0);//externalfileattributes(unused)
- writeInt(e.offset);//relativeoffsetoflocalheader
- writeBytes(nameBytes,0,nameBytes.length);
- if(e.extra!=null){
- writeBytes(e.extra,0,e.extra.length);
- }
- if(commentBytes!=null){
- writeBytes(commentBytes,0,commentBytes.length);
- }
- }
- /*
- *Writesendofcentraldirectory(END)header.
- */
- privatevoidwriteEND(longoff,longlen)throwsIOException{
- writeInt(ENDSIG);//ENDrecordsignature
- writeShort(0);//numberofthisdisk
- writeShort(0);//centraldirectorystartdisk
- writeShort(entries.size());//numberofdirectoryentriesondisk
- writeShort(entries.size());//totalnumberofdirectoryentries
- writeInt(len);//lengthofcentraldirectory
- writeInt(off);//offsetofcentraldirectory
- if(comment!=null){//zipfilecomment
- //byte[]b=getUTF8Bytes(comment);
- byte[]b=null;
- try{
- if(this.encoding.toUpperCase().equals("UTF-8"))
- b=getUTF8Bytes(comment);
- else
- b=comment.getBytes(this.encoding);
- }catch(ExceptionbyteE){
- b=getUTF8Bytes(comment);
- }
- writeShort(b.length);
- writeBytes(b,0,b.length);
- }else{
- writeShort(0);
- }
- }
- /*
- *Writesa16-bitshorttotheoutputstreaminlittle-endianbyteorder.
- */
- privatevoidwriteShort(intv)throwsIOException{
- OutputStreamout=this.out;
- out.write((v>>>0)&0xff);
- out.write((v>>>8)&0xff);
- written+=2;
- }
- /*
- *Writesa32-bitinttotheoutputstreaminlittle-endianbyteorder.
- */
- privatevoidwriteInt(longv)throwsIOException{
- OutputStreamout=this.out;
- out.write((int)((v>>>0)&0xff));
- out.write((int)((v>>>8)&0xff));
- out.write((int)((v>>>16)&0xff));
- out.write((int)((v>>>24)&0xff));
- written+=4;
- }
- /*
- *Writesanarrayofbytestotheoutputstream.
- */
- privatevoidwriteBytes(byte[]b,intoff,intlen)throwsIOException{
- super.out.write(b,off,len);
- written+=len;
- }
- /*
- *ReturnsthelengthofString'sUTF8encoding.
- */
- staticintgetUTF8Length(Strings){
- intcount=0;
- for(inti=0;i<s.length();i++){
- charch=s.charAt(i);
- if(ch<=0x7f){
- count++;
- }elseif(ch<=0x7ff){
- count+=2;
- }else{
- count+=3;
- }
- }
- returncount;
- }
- /*
- *ReturnsanarrayofbytesrepresentingtheUTF8encodingofthespecified
- *String.
- */
- privatestaticbyte[]getUTF8Bytes(Strings){
- char[]c=s.toCharArray();
- intlen=c.length;
- //Countthenumberofencodedbytes...
- intcount=0;
- for(inti=0;i<len;i++){
- intch=c[i];
- if(ch<=0x7f){
- count++;
- }elseif(ch<=0x7ff){
- count+=2;
- }else{
- count+=3;
- }
- }
- //Nowreturntheencodedbytes...
- byte[]b=newbyte[count];
- intoff=0;
- for(inti=0;i<len;i++){
- intch=c[i];
- if(ch<=0x7f){
- b[off++]=(byte)ch;
- }elseif(ch<=0x7ff){
- b[off++]=(byte)((ch>>6)|0xc0);
- b[off++]=(byte)((ch&0x3f)|0x80);
- }else{
- b[off++]=(byte)((ch>>12)|0xe0);
- b[off++]=(byte)(((ch>>6)&0x3f)|0x80);
- b[off++]=(byte)((ch&0x3f)|0x80);
- }
- }
- returnb;
- }
- }
剩下的工作就是編寫壓縮和解壓縮的功能類了ZipUtil.java
- packagecom.work.util;
- importjava.io.BufferedInputStream;
- importjava.io.BufferedOutputStream;
- importjava.io.File;
- importjava.io.FileInputStream;
- importjava.io.FileNotFoundException;
- importjava.io.FileOutputStream;
- importjava.io.IOException;
- importjava.io.InputStream;
- importorg.apache.commons.logging.Log;
- importorg.apache.commons.logging.LogFactory;
- importcom.work.util.zip.ZipInputStream;
- importcom.work.util.zip.ZipOutputStream;
- importcom.work.util.zip.ZipEntry;
- /**
- *@projectproxool-0.9.1中的java.util.zip包和此類聯合使用
- *@authorwangmingjie
- *
- */
- publicclassZipUtil{
- privatestaticLoglog=LogFactory.getLog(ZipUtil.class);
- /**
- *解壓縮文件夾。
- *
- *@paramsrcFilename
- *@paramdestFilename
- *@paramoverwrite
- *@throwsIOException
- */
- publicvoidunzipDir(StringsrcFilename,booleanoverwrite)throwsIOException{
- FilesrcFile=newFile(srcFilename);
- //首先判斷源文件是否存在
- if(!srcFile.exists()){
- thrownewFileNotFoundException("Cannotfindthesourcefile:"
- +srcFile.getAbsolutePath());
- }
- //判斷源文件是否可讀
- if(!srcFile.canRead()){
- thrownewIOException("Cannotreadthesourcefile:"
- +srcFile.getAbsolutePath());
- }
- FileInputStreamfin=null;
- BufferedInputStreaminputStream=null;
- ZipInputStreamzipInputStream=null;
- try{
- fin=newFileInputStream(srcFile);
- inputStream=newBufferedInputStream(fin);
- zipInputStream=newZipInputStream(inputStream,"gbk");//在這裏設置編碼格式,解決文件名和備註亂碼問題
- ZipEntryzipEntry=null;
- StringtempFileName=null;
- while((zipEntry=zipInputStream.getNextEntry())!=null){
- tempFileName=zipEntry.getName();
- if(zipEntry.isDirectory()){
- //創建文件夾
- FileUtil.createDirs(tempFileName,true);
- }else{
- tempFileName=tempFileName.replace("\\","/");
- //System.out.println("文件夾="+tempFileName.substring(0,tempFileName.lastIndexOf("/")));
- FileUtil.createDirs(tempFileName.substring(0,tempFileName.lastIndexOf("/")),true);
- //System.out.println("tempFileName="+tempFileName);
- unzipFile(zipInputStream,tempFileName);//解壓縮
- }
- zipInputStream.closeEntry();//關閉當前ZIP條目並定位流以讀取下一個條目。
- //不寫上面的一句,程序也能夠正常運行。
- }
- }finally{
- if(zipInputStream!=null){
- try{
- zipInputStream.close();
- }catch(IOExceptionex){
- //justignore
- }
- }
- if(inputStream!=null){
- try{
- inputStream.close();
- }catch(IOExceptionex){