用java实现zip压缩和解压缩功能。

 本文使用了jdk1.5.0_13的源代码。(java.uti.zip*)

实现方法:首先将java.uti.zip中的源代码解压出来。找到DeflaterOutputStream、InflaterInputStream、ZipConstants、ZipEntry、ZipInputStream、ZipOutputStream,放到新的包com.work.util.zip中,重新组织这些文件的import,能使用当前包中类的就使用当前包中的类。

重点要修改的类:ZipEntry,修改内容如下:

  1. //修改对应的程序,在这里加载zip库
  2.     static {
  3.         /* load the zip library */
  4.         java.security.AccessController
  5.                 .doPrivileged(new sun.security.action.LoadLibraryAction("zip"));
  6. //      initIDs();
  7.     }
  8. //  static {
  9. //      /* Zip library is loaded from System.initializeSystemClass */
  10. //      initIDs();
  11. //  }
  12. //  private static native void initIDs();

其次修改ZipInputStream,大约在279行。

  1. // ZipEntry e = createZipEntry(getUTF8String(b, 0, len));
  2.         ZipEntry e = null;
  3.         try {
  4.             if (this.encoding.toUpperCase().equals("UTF-8"))
  5.                 e = createZipEntry(getUTF8String(b, 0, len));
  6.             else
  7.                 e = createZipEntry(new String(b, 0, len, this.encoding));
  8.         } catch (Exception byteE) {
  9.             e = createZipEntry(getUTF8String(b, 0, len));
  10.         }
  11. //增加构造方法
  12. private String encoding = "UTF-8";
  13.  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类,源代码如下:

  1. /*
  2.  * @(#)ZipOutputStream.java 1.31 03/12/19
  3.  *
  4.  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5.  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6.  */
  7. package com.work.util.zip;
  8. import java.io.IOException;
  9. import java.io.OutputStream;
  10. import java.util.Enumeration;
  11. import java.util.Hashtable;
  12. import java.util.Vector;
  13. import java.util.zip.CRC32;
  14. import java.util.zip.Deflater;
  15. import java.util.zip.ZipException;
  16. /**
  17.  * This class implements an output stream filter for writing files in the ZIP
  18.  * file format. Includes support for both compressed and uncompressed entries.
  19.  * 
  20.  * @author David Connelly
  21.  * @version 1.31, 12/19/03
  22.  */
  23. public class ZipOutputStream extends DeflaterOutputStream implements
  24.         ZipConstants {
  25.     private ZipEntry entry;
  26.     private Vector entries = new Vector();
  27.     private Hashtable names = new Hashtable();
  28.     private CRC32 crc = new CRC32();
  29.     private long written = 0;
  30.     private long locoff = 0;
  31.     private String comment;
  32.     private int method = DEFLATED;
  33.     private boolean finished;
  34.     private boolean closed = false;
  35.     /**
  36.      * Check to make sure that this stream has not been closed
  37.      */
  38.     private void ensureOpen() throws IOException {
  39.         if (closed) {
  40.             throw new IOException("Stream closed");
  41.         }
  42.     }
  43.     /**
  44.      * Compression method for uncompressed (STORED) entries.
  45.      */
  46.     public static final int STORED = ZipEntry.STORED;
  47.     /**
  48.      * Compression method for compressed (DEFLATED) entries.
  49.      */
  50.     public static final int DEFLATED = ZipEntry.DEFLATED;
  51.     private String encoding = "UTF-8";
  52.     public ZipOutputStream(OutputStream out, String encoding) {
  53.         super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
  54.         usesDefaultDeflater = true;
  55.         this.encoding = encoding;
  56.     }
  57.     /**
  58.      * Creates a new ZIP output stream.
  59.      * 
  60.      * @param out
  61.      *            the actual output stream
  62.      */
  63.     public ZipOutputStream(OutputStream out) {
  64.         super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
  65.         usesDefaultDeflater = true;
  66.     }
  67.     /**
  68.      * Sets the ZIP file comment.
  69.      * 
  70.      * @param comment
  71.      *            the comment string
  72.      * @exception IllegalArgumentException
  73.      *                if the length of the specified ZIP file comment is greater
  74.      *                than 0xFFFF bytes
  75.      */
  76.     public void setComment(String comment) {
  77.         if (comment != null && comment.length() > 0xffff / 3
  78.                 && getUTF8Length(comment) > 0xffff) {
  79.             throw new IllegalArgumentException("ZIP file comment too long.");
  80.         }
  81.         this.comment = comment;
  82.     }
  83.     /**
  84.      * Sets the default compression method for subsequent entries. This default
  85.      * will be used whenever the compression method is not specified for an
  86.      * individual ZIP file entry, and is initially set to DEFLATED.
  87.      * 
  88.      * @param method
  89.      *            the default compression method
  90.      * @exception IllegalArgumentException
  91.      *                if the specified compression method is invalid
  92.      */
  93.     public void setMethod(int method) {
  94.         if (method != DEFLATED && method != STORED) {
  95.             throw new IllegalArgumentException("invalid compression method");
  96.         }
  97.         this.method = method;
  98.     }
  99.     /**
  100.      * Sets the compression level for subsequent entries which are DEFLATED. The
  101.      * default setting is DEFAULT_COMPRESSION.
  102.      * 
  103.      * @param level
  104.      *            the compression level (0-9)
  105.      * @exception IllegalArgumentException
  106.      *                if the compression level is invalid
  107.      */
  108.     public void setLevel(int level) {
  109.         def.setLevel(level);
  110.     }
  111.     /**
  112.      * Begins writing a new ZIP file entry and positions the stream to the start
  113.      * of the entry data. Closes the current entry if still active. The default
  114.      * compression method will be used if no compression method was specified
  115.      * for the entry, and the current time will be used if the entry has no set
  116.      * modification time.
  117.      * 
  118.      * @param e
  119.      *            the ZIP entry to be written
  120.      * @exception ZipException
  121.      *                if a ZIP format error has occurred
  122.      * @exception IOException
  123.      *                if an I/O error has occurred
  124.      */
  125.     public void putNextEntry(ZipEntry e) throws IOException {
  126.         ensureOpen();
  127.         if (entry != null) {
  128.             closeEntry(); // close previous entry
  129.         }
  130.         if (e.time == -1) {
  131.             e.setTime(System.currentTimeMillis());
  132.         }
  133.         if (e.method == -1) {
  134.             e.method = method; // use default method
  135.         }
  136.         switch (e.method) {
  137.         case DEFLATED:
  138.             if (e.size == -1 || e.csize == -1 || e.crc == -1) {
  139.                 // store size, compressed size, and crc-32 in data descriptor
  140.                 // immediately following the compressed entry data
  141.                 e.flag = 8;
  142.             } else if (e.size != -1 && e.csize != -1 && e.crc != -1) {
  143.                 // store size, compressed size, and crc-32 in LOC header
  144.                 e.flag = 0;
  145.             } else {
  146.                 throw new ZipException(
  147.                         "DEFLATED entry missing size, compressed size, or crc-32");
  148.             }
  149.             e.version = 20;
  150.             break;
  151.         case STORED:
  152.             // compressed size, uncompressed size, and crc-32 must all be
  153.             // set for entries using STORED compression method
  154.             if (e.size == -1) {
  155.                 e.size = e.csize;
  156.             } else if (e.csize == -1) {
  157.                 e.csize = e.size;
  158.             } else if (e.size != e.csize) {
  159.                 throw new ZipException(
  160.                         "STORED entry where compressed != uncompressed size");
  161.             }
  162.             if (e.size == -1 || e.crc == -1) {
  163.                 throw new ZipException(
  164.                         "STORED entry missing size, compressed size, or crc-32");
  165.             }
  166.             e.version = 10;
  167.             e.flag = 0;
  168.             break;
  169.         default:
  170.             throw new ZipException("unsupported compression method");
  171.         }
  172.         e.offset = written;
  173.         if (names.put(e.name, e) != null) {
  174.             throw new ZipException("duplicate entry: " + e.name);
  175.         }
  176.         writeLOC(e);
  177.         entries.addElement(e);
  178.         entry = e;
  179.     }
  180.     /**
  181.      * Closes the current ZIP entry and positions the stream for writing the
  182.      * next entry.
  183.      * 
  184.      * @exception ZipException
  185.      *                if a ZIP format error has occurred
  186.      * @exception IOException
  187.      *                if an I/O error has occurred
  188.      */
  189.     public void closeEntry() throws IOException {
  190.         ensureOpen();
  191.         ZipEntry e = entry;
  192.         if (e != null) {
  193.             switch (e.method) {
  194.             case DEFLATED:
  195.                 def.finish();
  196.                 while (!def.finished()) {
  197.                     deflate();
  198.                 }
  199.                 if ((e.flag & 8) == 0) {
  200.                     // verify size, compressed size, and crc-32 settings
  201.                     if (e.size != def.getBytesRead()) {
  202.                         throw new ZipException("invalid entry size (expected "
  203.                                 + e.size + " but got " + def.getBytesRead()
  204.                                 + " bytes)");
  205.                     }
  206.                     if (e.csize != def.getBytesWritten()) {
  207.                         throw new ZipException(
  208.                                 "invalid entry compressed size (expected "
  209.                                         + e.csize + " but got "
  210.                                         + def.getBytesWritten() + " bytes)");
  211.                     }
  212.                     if (e.crc != crc.getValue()) {
  213.                         throw new ZipException(
  214.                                 "invalid entry CRC-32 (expected 0x"
  215.                                         + Long.toHexString(e.crc)
  216.                                         + " but got 0x"
  217.                                         + Long.toHexString(crc.getValue())
  218.                                         + ")");
  219.                     }
  220.                 } else {
  221.                     e.size = def.getBytesRead();
  222.                     e.csize = def.getBytesWritten();
  223.                     e.crc = crc.getValue();
  224.                     writeEXT(e);
  225.                 }
  226.                 def.reset();
  227.                 written += e.csize;
  228.                 break;
  229.             case STORED:
  230.                 // we already know that both e.size and e.csize are the same
  231.                 if (e.size != written - locoff) {
  232.                     throw new ZipException("invalid entry size (expected "
  233.                             + e.size + " but got " + (written - locoff)
  234.                             + " bytes)");
  235.                 }
  236.                 if (e.crc != crc.getValue()) {
  237.                     throw new ZipException("invalid entry crc-32 (expected 0x"
  238.                             + Long.toHexString(e.crc) + " but got 0x"
  239.                             + Long.toHexString(crc.getValue()) + ")");
  240.                 }
  241.                 break;
  242.             default:
  243.                 throw new InternalError("invalid compression method");
  244.             }
  245.             crc.reset();
  246.             entry = null;
  247.         }
  248.     }
  249.     /**
  250.      * Writes an array of bytes to the current ZIP entry data. This method will
  251.      * block until all the bytes are written.
  252.      * 
  253.      * @param b
  254.      *            the data to be written
  255.      * @param off
  256.      *            the start offset in the data
  257.      * @param len
  258.      *            the number of bytes that are written
  259.      * @exception ZipException
  260.      *                if a ZIP file error has occurred
  261.      * @exception IOException
  262.      *                if an I/O error has occurred
  263.      */
  264.     public synchronized void write(byte[] b, int off, int len)
  265.             throws IOException {
  266.         ensureOpen();
  267.         if (off < 0 || len < 0 || off > b.length - len) {
  268.             throw new IndexOutOfBoundsException();
  269.         } else if (len == 0) {
  270.             return;
  271.         }
  272.         if (entry == null) {
  273.             throw new ZipException("no current ZIP entry");
  274.         }
  275.         switch (entry.method) {
  276.         case DEFLATED:
  277.             super.write(b, off, len);
  278.             break;
  279.         case STORED:
  280.             written += len;
  281.             if (written - locoff > entry.size) {
  282.                 throw new ZipException(
  283.                         "attempt to write past end of STORED entry");
  284.             }
  285.             out.write(b, off, len);
  286.             break;
  287.         default:
  288.             throw new InternalError("invalid compression method");
  289.         }
  290.         crc.update(b, off, len);
  291.     }
  292.     /**
  293.      * Finishes writing the contents of the ZIP output stream without closing
  294.      * the underlying stream. Use this method when applying multiple filters in
  295.      * succession to the same output stream.
  296.      * 
  297.      * @exception ZipException
  298.      *                if a ZIP file error has occurred
  299.      * @exception IOException
  300.      *                if an I/O exception has occurred
  301.      */
  302.     public void finish() throws IOException {
  303.         ensureOpen();
  304.         if (finished) {
  305.             return;
  306.         }
  307.         if (entry != null) {
  308.             closeEntry();
  309.         }
  310.         if (entries.size() < 1) {
  311.             throw new ZipException("ZIP file must have at least one entry");
  312.         }
  313.         // write central directory
  314.         long off = written;
  315.         Enumeration e = entries.elements();
  316.         while (e.hasMoreElements()) {
  317.             writeCEN((ZipEntry) e.nextElement());
  318.         }
  319.         writeEND(off, written - off);
  320.         finished = true;
  321.     }
  322.     /**
  323.      * Closes the ZIP output stream as well as the stream being filtered.
  324.      * 
  325.      * @exception ZipException
  326.      *                if a ZIP file error has occurred
  327.      * @exception IOException
  328.      *                if an I/O error has occurred
  329.      */
  330.     public void close() throws IOException {
  331.         if (!closed) {
  332.             super.close();
  333.             closed = true;
  334.         }
  335.     }
  336.     /*
  337.      * Writes local file (LOC) header for specified entry.
  338.      */
  339.     private void writeLOC(ZipEntry e) throws IOException {
  340.         writeInt(LOCSIG); // LOC header signature
  341.         writeShort(e.version); // version needed to extract
  342.         writeShort(e.flag); // general purpose bit flag
  343.         writeShort(e.method); // compression method
  344.         writeInt(e.time); // last modification time
  345.         if ((e.flag & 8) == 8) {
  346.             // store size, uncompressed size, and crc-32 in data descriptor
  347.             // immediately following compressed entry data
  348.             writeInt(0);
  349.             writeInt(0);
  350.             writeInt(0);
  351.         } else {
  352.             writeInt(e.crc); // crc-32
  353.             writeInt(e.csize); // compressed size
  354.             writeInt(e.size); // uncompressed size
  355.         }
  356.         // byte[] nameBytes = getUTF8Bytes(e.name);
  357.         byte[] nameBytes = null;
  358.         try {
  359.             if (this.encoding.toUpperCase().equals("UTF-8"))
  360.                 nameBytes = getUTF8Bytes(e.name);
  361.             else
  362.                 nameBytes = e.name.getBytes(this.encoding);
  363.         } catch (Exception byteE) {
  364.             nameBytes = getUTF8Bytes(e.name);
  365.         }
  366.         writeShort(nameBytes.length);
  367.         writeShort(e.extra != null ? e.extra.length : 0);
  368.         writeBytes(nameBytes, 0, nameBytes.length);
  369.         if (e.extra != null) {
  370.             writeBytes(e.extra, 0, e.extra.length);
  371.         }
  372.         locoff = written;
  373.     }
  374.     /*
  375.      * Writes extra data descriptor (EXT) for specified entry.
  376.      */
  377.     private void writeEXT(ZipEntry e) throws IOException {
  378.         writeInt(EXTSIG); // EXT header signature
  379.         writeInt(e.crc); // crc-32
  380.         writeInt(e.csize); // compressed size
  381.         writeInt(e.size); // uncompressed size
  382.     }
  383.     /*
  384.      * Write central directory (CEN) header for specified entry. REMIND: add
  385.      * support for file attributes
  386.      */
  387.     private void writeCEN(ZipEntry e) throws IOException {
  388.         writeInt(CENSIG); // CEN header signature
  389.         writeShort(e.version); // version made by
  390.         writeShort(e.version); // version needed to extract
  391.         writeShort(e.flag); // general purpose bit flag
  392.         writeShort(e.method); // compression method
  393.         writeInt(e.time); // last modification time
  394.         writeInt(e.crc); // crc-32
  395.         writeInt(e.csize); // compressed size
  396.         writeInt(e.size); // uncompressed size
  397.         // byte[] nameBytes = getUTF8Bytes(e.name);
  398.         byte[] nameBytes = null;
  399.         try {
  400.             if (this.encoding.toUpperCase().equals("UTF-8"))
  401.                 nameBytes = getUTF8Bytes(e.name);
  402.             else
  403.                 nameBytes = e.name.getBytes(this.encoding);
  404.         } catch (Exception byteE) {
  405.             nameBytes = getUTF8Bytes(e.name);
  406.         }
  407.         writeShort(nameBytes.length);
  408.         writeShort(e.extra != null ? e.extra.length : 0);
  409.         byte[] commentBytes;
  410.         if (e.comment != null) {
  411.             
  412.             //commentBytes = getUTF8Bytes(e.comment);
  413.             
  414.             try {
  415.                 if (this.encoding.toUpperCase().equals("UTF-8"))
  416.                     commentBytes = getUTF8Bytes(e.comment);
  417.                 else
  418.                     commentBytes = e.comment.getBytes(this.encoding);
  419.             } catch (Exception byteE) {
  420.                 commentBytes = getUTF8Bytes(e.comment);
  421.             }           
  422.             
  423.             writeShort(commentBytes.length);
  424.         } else {
  425.             commentBytes = null;
  426.             writeShort(0);
  427.         }
  428.         writeShort(0); // starting disk number
  429.         writeShort(0); // internal file attributes (unused)
  430.         writeInt(0); // external file attributes (unused)
  431.         writeInt(e.offset); // relative offset of local header
  432.         writeBytes(nameBytes, 0, nameBytes.length);
  433.         if (e.extra != null) {
  434.             writeBytes(e.extra, 0, e.extra.length);
  435.         }
  436.         if (commentBytes != null) {
  437.             writeBytes(commentBytes, 0, commentBytes.length);
  438.         }
  439.     }
  440.     /*
  441.      * Writes end of central directory (END) header.
  442.      */
  443.     private void writeEND(long off, long len) throws IOException {
  444.         writeInt(ENDSIG); // END record signature
  445.         writeShort(0); // number of this disk
  446.         writeShort(0); // central directory start disk
  447.         writeShort(entries.size()); // number of directory entries on disk
  448.         writeShort(entries.size()); // total number of directory entries
  449.         writeInt(len); // length of central directory
  450.         writeInt(off); // offset of central directory
  451.         if (comment != null) { // zip file comment
  452.             //byte[] b = getUTF8Bytes(comment);
  453.             byte[] b = null;
  454.             
  455.             try {
  456.                 if (this.encoding.toUpperCase().equals("UTF-8"))
  457.                     b = getUTF8Bytes(comment);
  458.                 else
  459.                     b = comment.getBytes(this.encoding);
  460.             } catch (Exception byteE) {
  461.                 b = getUTF8Bytes(comment);
  462.             }               
  463.             writeShort(b.length);
  464.             writeBytes(b, 0, b.length);
  465.         } else {
  466.             writeShort(0);
  467.         }
  468.     }
  469.     /*
  470.      * Writes a 16-bit short to the output stream in little-endian byte order.
  471.      */
  472.     private void writeShort(int v) throws IOException {
  473.         OutputStream out = this.out;
  474.         out.write((v >>> 0) & 0xff);
  475.         out.write((v >>> 8) & 0xff);
  476.         written += 2;
  477.     }
  478.     /*
  479.      * Writes a 32-bit int to the output stream in little-endian byte order.
  480.      */
  481.     private void writeInt(long v) throws IOException {
  482.         OutputStream out = this.out;
  483.         out.write((int) ((v >>> 0) & 0xff));
  484.         out.write((int) ((v >>> 8) & 0xff));
  485.         out.write((int) ((v >>> 16) & 0xff));
  486.         out.write((int) ((v >>> 24) & 0xff));
  487.         written += 4;
  488.     }
  489.     /*
  490.      * Writes an array of bytes to the output stream.
  491.      */
  492.     private void writeBytes(byte[] b, int off, int len) throws IOException {
  493.         super.out.write(b, off, len);
  494.         written += len;
  495.     }
  496.     /*
  497.      * Returns the length of String's UTF8 encoding.
  498.      */
  499.     static int getUTF8Length(String s) {
  500.         int count = 0;
  501.         for (int i = 0; i < s.length(); i++) {
  502.             char ch = s.charAt(i);
  503.             if (ch <= 0x7f) {
  504.                 count++;
  505.             } else if (ch <= 0x7ff) {
  506.                 count += 2;
  507.             } else {
  508.                 count += 3;
  509.             }
  510.         }
  511.         return count;
  512.     }
  513.     /*
  514.      * Returns an array of bytes representing the UTF8 encoding of the specified
  515.      * String.
  516.      */
  517.     private static byte[] getUTF8Bytes(String s) {
  518.         char[] c = s.toCharArray();
  519.         int len = c.length;
  520.         // Count the number of encoded bytes...
  521.         int count = 0;
  522.         for (int i = 0; i < len; i++) {
  523.             int ch = c[i];
  524.             if (ch <= 0x7f) {
  525.                 count++;
  526.             } else if (ch <= 0x7ff) {
  527.                 count += 2;
  528.             } else {
  529.                 count += 3;
  530.             }
  531.         }
  532.         // Now return the encoded bytes...
  533.         byte[] b = new byte[count];
  534.         int off = 0;
  535.         for (int i = 0; i < len; i++) {
  536.             int ch = c[i];
  537.             if (ch <= 0x7f) {
  538.                 b[off++] = (byte) ch;
  539.             } else if (ch <= 0x7ff) {
  540.                 b[off++] = (byte) ((ch >> 6) | 0xc0);
  541.                 b[off++] = (byte) ((ch & 0x3f) | 0x80);
  542.             } else {
  543.                 b[off++] = (byte) ((ch >> 12) | 0xe0);
  544.                 b[off++] = (byte) (((ch >> 6) & 0x3f) | 0x80);
  545.                 b[off++] = (byte) ((ch & 0x3f) | 0x80);
  546.             }
  547.         }
  548.         return b;
  549.     }
  550. }

剩下的工作就是编写压缩和解压缩的功能类了ZipUtil.java

 

  1. package com.work.util;
  2. import java.io.BufferedInputStream;
  3. import java.io.BufferedOutputStream;
  4. import java.io.File;
  5. import java.io.FileInputStream;
  6. import java.io.FileNotFoundException;
  7. import java.io.FileOutputStream;
  8. import java.io.IOException;
  9. import java.io.InputStream;
  10. import org.apache.commons.logging.Log;
  11. import org.apache.commons.logging.LogFactory;
  12. import com.work.util.zip.ZipInputStream;
  13. import com.work.util.zip.ZipOutputStream;
  14. import com.work.util.zip.ZipEntry;
  15. /**
  16.  * @project proxool-0.9.1 中的java.util.zip包和此类联合使用
  17.  * @author wangmingjie
  18.  * 
  19.  */
  20. public class ZipUtil {
  21.     private static Log log = LogFactory.getLog(ZipUtil.class);
  22.     /**
  23.      * 解压缩文件夹。
  24.      * 
  25.      * @param srcFilename
  26.      * @param destFilename
  27.      * @param overwrite
  28.      * @throws IOException
  29.      */
  30.     public void unzipDir(String srcFilename,boolean overwrite) throws IOException {
  31.         File srcFile = new File(srcFilename);
  32.         // 首先判断源文件是否存在
  33.         if (!srcFile.exists()) {
  34.             throw new FileNotFoundException("Cannot find the source file: "
  35.                     + srcFile.getAbsolutePath());
  36.         }
  37.         // 判断源文件是否可读
  38.         if (!srcFile.canRead()) {
  39.             throw new IOException("Cannot read the source file: "
  40.                     + srcFile.getAbsolutePath());
  41.         }
  42.         FileInputStream fin = null;
  43.         BufferedInputStream inputStream = null;
  44.         ZipInputStream zipInputStream = null;
  45.         try {
  46.             fin = new FileInputStream(srcFile);
  47.             inputStream = new BufferedInputStream(fin);
  48.             zipInputStream = new ZipInputStream(inputStream, "gbk");//在这里设置编码格式,解决文件名和备注乱码问题
  49.             ZipEntry zipEntry = null;
  50.             String tempFileName = null;
  51.             while ((zipEntry = zipInputStream.getNextEntry()) != null) {
  52.                 
  53.                 tempFileName = zipEntry.getName();
  54.                 if (zipEntry.isDirectory()) {
  55.                     // 创建文件夹
  56.                     FileUtil.createDirs(tempFileName, true);
  57.                 } else {
  58.                     tempFileName = tempFileName.replace("//", "/");
  59.                     //System.out.println("文件夹=" + tempFileName.substring(0,tempFileName.lastIndexOf("/")));
  60.                     FileUtil.createDirs(tempFileName.substring(0,tempFileName.lastIndexOf("/")), true);
  61.                     //System.out.println("tempFileName=" + tempFileName);
  62.                     unzipFile(zipInputStream, tempFileName); // 解压缩
  63.                 }
  64.                 zipInputStream.closeEntry();//关闭当前 ZIP 条目并定位流以读取下一个条目。
  65.                 //不写上面的一句,程序也能够正常运行。
  66.             }
  67.             
  68.         } finally {
  69.             if (zipInputStream != null) {
  70.                 try {
  71.                     zipInputStream.close();
  72.                 } catch (IOException ex) {
  73.                     // just ignore
  74.                 }
  75.             }
  76.             if (inputStream != null) {
  77.                 try {
  78.                     inputStream.close();
  79.                 } catch (IOException ex) {
  80.                     // just ignore
  81.                 }
  82.             }
  83.             if (fin != null) {
  84.                 try {
  85.                     fin.close();
  86.                 } catch (IOException ex) {
  87.                     // just ignore
  88.                 }
  89.             }
  90.         }
  91.     }
  92.     /**
  93.      * 创建解压缩的文件
  94.      * 
  95.      * @param srcFilename
  96.      * @param zipInputStream
  97.      * @throws IOException
  98.      */
  99.     private void unzipFile(InputStream zipInputStream, String destFileName)
  100.             throws IOException {
  101.         FileOutputStream fout = null;
  102.         BufferedOutputStream outputStream = null;
  103.         byte[] block = new byte[1024];
  104.         try {
  105.             if(log.isDebugEnabled()){
  106.                 log.debug("要生成的文件名称为:" + destFileName);
  107.             }
  108.             
  109.             File destFile = new File(destFileName);
  110.             // 如果要覆盖已经存在的目标文件,首先判断是否目标文件可写。
  111.             if (destFile.exists()) {
  112.                 if (!destFile.canWrite()) {
  113.                     throw new IOException("Cannot write the destination file: "
  114.                             + destFile.getAbsolutePath());
  115.                 }
  116.             } else {
  117.                 // 不存在就创建一个新的空文件。
  118.                 if (!destFile.createNewFile()) {
  119.                     throw new IOException("Cannot write the destination file: "
  120.                             + destFile.getAbsolutePath());
  121.                 }
  122.             }
  123.             fout = new FileOutputStream(destFile);
  124.             outputStream = new BufferedOutputStream(fout);
  125.             // 开始从zip文件中读取数据
  126.             while (true) {
  127.                 int readLength = zipInputStream.read(block);
  128.                 if (readLength == -1)
  129.                     break;// end of file
  130.                 outputStream.write(block, 0, readLength);
  131.             }
  132.             outputStream.flush();
  133.         } finally {
  134.             if (outputStream != null) {
  135.                 try {
  136.                     outputStream.close();
  137.                 } catch (IOException ex) {
  138.                     // just ignore
  139.                 }
  140.             }
  141.             if (fout != null) {
  142.                 try {
  143.                     fout.close();
  144.                 } catch (IOException ex) {
  145.                     // just ignore
  146.                 }
  147.             }
  148.         }
  149.     }
  150.     /**
  151.      * 解压缩单个文件。程序测试的过度函数!
  152.      * 
  153.      * @param srcFilename
  154.      * @param destFilename
  155.      * @param overwrite
  156.      * @throws IOException
  157.      */
  158.     public void unzipFile(String srcFilename, String destFilename,
  159.             boolean overwrite) throws IOException {
  160.         File srcFile = new File(srcFilename);
  161.         // 首先判断源文件是否存在
  162.         if (!srcFile.exists()) {
  163.             throw new FileNotFoundException("Cannot find the source file: "
  164.                     + srcFile.getAbsolutePath());
  165.         }
  166.         // 判断源文件是否可读
  167.         if (!srcFile.canRead()) {
  168.             throw new IOException("Cannot read the source file: "
  169.                     + srcFile.getAbsolutePath());
  170.         }
  171.         FileInputStream fin = null;
  172.         BufferedInputStream inputStream = null;
  173.         ZipInputStream zipInputStream = null;
  174.         FileOutputStream fout = null;
  175.         BufferedOutputStream outputStream = null;
  176.         byte[] block = new byte[1024];
  177.         try {
  178.             fin = new FileInputStream(srcFile);
  179.             inputStream = new BufferedInputStream(fin);
  180.             zipInputStream = new ZipInputStream(inputStream, "gbk");
  181.             ZipEntry zipEntry = zipInputStream.getNextEntry();
  182.             if (destFilename == null || destFilename.trim().equals("")) {
  183.                 destFilename = zipEntry.getName();
  184.             }
  185.             System.out.println("解压缩生成的文件名称为:" + destFilename);
  186.             File destFile = new File(destFilename);
  187.             if (overwrite == false) {
  188.                 // 目标文件存在就不覆盖
  189.                 if (destFile.exists())
  190.                     return;
  191.             } else {
  192.                 // 如果要覆盖已经存在的目标文件,首先判断是否目标文件可写。
  193.                 if (destFile.exists()) {
  194.                     if (!destFile.canWrite()) {
  195.                         throw new IOException(
  196.                                 "Cannot write the destination file: "
  197.                                         + destFile.getAbsolutePath());
  198.                     }
  199.                 } else {
  200.                     // 不存在就创建一个新的空文件。
  201.                     if (!destFile.createNewFile()) {
  202.                         throw new IOException(
  203.                                 "Cannot write the destination file: "
  204.                                         + destFile.getAbsolutePath());
  205.                     }
  206.                 }
  207.             }
  208.             fout = new FileOutputStream(destFile);
  209.             outputStream = new BufferedOutputStream(fout);
  210.             // 开始从zip文件中读取数据
  211.             while (true) {
  212.                 int readLength = zipInputStream.read(block);
  213.                 if (readLength == -1)
  214.                     break;// end of file
  215.                 outputStream.write(block, 0, readLength);
  216.             }
  217.             outputStream.flush();
  218.         } finally {
  219.             if (zipInputStream != null) {
  220.                 try {
  221.                     zipInputStream.close();
  222.                 } catch (IOException ex) {
  223.                     // just ignore
  224.                 }
  225.             }
  226.             if (inputStream != null) {
  227.                 try {
  228.                     inputStream.close();
  229.                 } catch (IOException ex) {
  230.                     // just ignore
  231.                 }
  232.             }
  233.             if (fin != null) {
  234.                 try {
  235.                     fin.close();
  236.                 } catch (IOException ex) {
  237.                     // just ignore
  238.                 }
  239.             }
  240.             if (outputStream != null) {
  241.                 try {
  242.                     outputStream.close();
  243.                 } catch (IOException ex) {
  244.                     // just ignore
  245.                 }
  246.             }
  247.             if (fout != null) {
  248.                 try {
  249.                     fout.close();
  250.                 } catch (IOException ex) {
  251.                     // just ignore
  252.                 }
  253.             }
  254.         }
  255.     }
  256.     /**
  257.      * 压缩单个文件。
  258.      * 
  259.      * @param srcFilename
  260.      * @param destFilename
  261.      * @param overwrite
  262.      * @throws IOException
  263.      */
  264.     /**
  265.      * @param srcFilename
  266.      * @param destDir  目标文件保存在哪个文件夹下面
  267.      * @param destFilename
  268.      * @param overwrite
  269.      * @throws IOException
  270.      */
  271.     public void zipFile(String srcFilename, String destDir,String destFilename,
  272.             boolean overwrite) throws IOException {
  273.         File srcFile = new File(srcFilename);
  274.         // 首先判断源文件是否存在
  275.         if (!srcFile.exists()) {
  276.             throw new FileNotFoundException("Cannot find the source file: "
  277.                     + srcFile.getAbsolutePath());
  278.         }
  279.         // 判断源文件是否可读
  280.         if (!srcFile.canRead()) {
  281.             throw new IOException("Cannot read the source file: "
  282.                     + srcFile.getAbsolutePath());
  283.         }
  284.         if (destFilename == null || destFilename.trim().equals("")) {
  285.             destFilename = srcFilename + ".zip";
  286.         } else {
  287.             destFilename += ".zip";
  288.         }
  289.         destDir = (destDir.endsWith("/") || destDir.endsWith("//"))?destDir.substring(0,destDir.length()-1):destDir;
  290.         
  291.         File destFile = new File(destDir+"/"+destFilename);
  292.         if (overwrite == false) {
  293.             // 目标文件存在就不覆盖
  294.             if (destFile.exists())
  295.                 return;
  296.         } else {
  297.             // 如果要覆盖已经存在的目标文件,首先判断是否目标文件可写。
  298.             if (destFile.exists()) {
  299.                 if (!destFile.canWrite()) {
  300.                     throw new IOException("Cannot write the destination file: "
  301.                             + destFile.getAbsolutePath());
  302.                 }
  303.             } else {
  304.                 // 不存在就创建一个新的空文件。
  305.                 if (!destFile.createNewFile()) {
  306.                     throw new IOException("Cannot write the destination file: "
  307.                             + destFile.getAbsolutePath());
  308.                 }
  309.             }
  310.         }
  311.         FileInputStream fin = null;
  312.         BufferedInputStream inputStream = null;
  313.         FileOutputStream fout = new FileOutputStream(destFile);
  314.         BufferedOutputStream outputStream = null;
  315.         ZipOutputStream zipOutputStream = null;
  316.         byte[] block = new byte[1024];
  317.         try {
  318.             fin = new FileInputStream(srcFile);
  319.             inputStream = new BufferedInputStream(fin);
  320.             outputStream = new BufferedOutputStream(fout);
  321.             zipOutputStream = new ZipOutputStream(outputStream, "gbk");
  322.             zipOutputStream.setComment("通过java程序压缩的,压缩时间为:"+DateUtil.getCurrentDateTime());
  323.             ZipEntry zipEntry = new ZipEntry(srcFile.getName());
  324.             zipEntry.setComment(" zipEntry通过java程序压缩的");
  325.             zipOutputStream.putNextEntry(zipEntry);
  326.             while (true) {
  327.                 int readLength = inputStream.read(block);
  328.                 if (readLength == -1)
  329.                     break;// end of file
  330.                 zipOutputStream.write(block, 0, readLength);
  331.             }
  332.             zipOutputStream.flush();
  333.             zipOutputStream.finish();
  334.         } finally {
  335.             if (inputStream != null) {
  336.                 try {
  337.                     inputStream.close();
  338.                 } catch (IOException ex) {
  339.                     // just ignore
  340.                 }
  341.             }
  342.             if (fin != null) {
  343.                 try {
  344.                     fin.close();
  345.                 } catch (IOException ex) {
  346.                     // just ignore
  347.                 }
  348.             }
  349.             if (zipOutputStream != null) {
  350.                 try {
  351.                     zipOutputStream.close();
  352.                 } catch (IOException ex) {
  353.                     // just ignore
  354.                 }
  355.             }
  356.             if (outputStream != null) {
  357.                 try {
  358.                     outputStream.close();
  359.                 } catch (IOException ex) {
  360.                     // just ignore
  361.                 }
  362.             }
  363.             if (fout != null) {
  364.                 try {
  365.                     fout.close();
  366.                 } catch (IOException ex) {
  367.                     // just ignore
  368.                 }
  369.             }
  370.         }
  371.     }
  372.     /**
  373.      * 
  374.      * @param srcFilename
  375.      *            源文件
  376.      * @param destFilename
  377.      *            目标文件名称,如果为空,那么就使用源文件的名称+.zip作为文件名
  378.      * @param overwrite
  379.      *            如果目标文件存在是否覆盖源文件,默认是不覆盖。
  380.      * @throws IOException
  381.      */
  382.     public void zipDir(String srcFilename, String destFilename,
  383.             boolean overwrite) throws IOException {
  384.         File srcFile = new File(srcFilename);
  385.         // 首先判断源文件是否存在
  386.         if (!srcFile.exists()) {
  387.             throw new FileNotFoundException("Cannot find the source file: "
  388.                     + srcFile.getAbsolutePath());
  389.         }
  390.         // 判断源文件是否可读
  391.         if (!srcFile.canRead()) {
  392.             throw new IOException("Cannot read the source file: "
  393.                     + srcFile.getAbsolutePath());
  394.         }
  395.         if (destFilename == null || destFilename.trim().equals("")) {
  396.             destFilename = srcFilename + ".zip";
  397.         } else {
  398.             destFilename += ".zip";
  399.         }
  400.         File destFile = new File(destFilename);
  401.         if (overwrite == false) {
  402.             // 目标文件存在就不覆盖
  403.             if (destFile.exists())
  404.                 return;
  405.         } else {
  406.             // 如果要覆盖已经存在的目标文件,首先判断是否目标文件可写。
  407.             if (destFile.exists()) {
  408.                 if (!destFile.canWrite()) {
  409.                     throw new IOException("Cannot write the destination file: "
  410.                             + destFile.getAbsolutePath());
  411.                 }
  412.             } else {
  413.                 // 不存在就创建一个新的空文件。
  414.                 if (!destFile.createNewFile()) {
  415.                     throw new IOException("Cannot write the destination file: "
  416.                             + destFile.getAbsolutePath());
  417.                 }
  418.             }
  419.         }
  420.         BufferedOutputStream outputStream = null;
  421.         ZipOutputStream zipOutputStream = null;
  422.         FileOutputStream fout = new FileOutputStream(destFile);
  423.         outputStream = new BufferedOutputStream(fout);
  424.         zipOutputStream = new ZipOutputStream(outputStream, "gbk");
  425.         zipOutputStream.setComment("通过java程序压缩的");
  426.         try {
  427.             zipDir(srcFile, zipOutputStream);// 压缩文件
  428.             zipOutputStream.flush();
  429.             zipOutputStream.finish();
  430.         } finally {
  431.             if (zipOutputStream != null) {
  432.                 try {
  433.                     zipOutputStream.close();
  434.                 } catch (IOException ex) {
  435.                     // just ignore
  436.                 }
  437.             }
  438.             if (outputStream != null) {
  439.                 try {
  440.                     outputStream.close();
  441.                 } catch (IOException ex) {
  442.                     // just ignore
  443.                 }
  444.             }
  445.             if (fout != null) {
  446.                 try {
  447.                     fout.close();
  448.                 } catch (IOException ex) {
  449.                     // just ignore
  450.                 }
  451.             }
  452.         }
  453.     }
  454.     /**
  455.      * 压缩文件夹
  456.      * 
  457.      * @param srcFile
  458.      * @param zipOutputStream
  459.      * @throws IOException
  460.      */
  461.     private void zipDir(File srcFile, ZipOutputStream zipOutputStream)
  462.             throws IOException {
  463.         if (srcFile.isFile()) {
  464.             if (log.isDebugEnabled()) {
  465.                 log.debug(srcFile.getAbsolutePath());
  466.             }
  467.             
  468.             System.out.println("要压缩的文件"+srcFile.getAbsolutePath());
  469.             FileInputStream fin = null;
  470.             BufferedInputStream inputStream = null;
  471.             byte[] block = new byte[1024];
  472.             try {
  473.                 fin = new FileInputStream(srcFile);
  474.                 inputStream = new BufferedInputStream(fin);
  475.                 ZipEntry zipEntry = new ZipEntry(srcFile.getAbsolutePath());// 获取文件的绝对路径
  476.                 zipOutputStream.putNextEntry(zipEntry);
  477.                 while (true) {
  478.                     int readLength = inputStream.read(block);
  479.                     if (readLength == -1)
  480.                         break;// end of file
  481.                     zipOutputStream.write(block, 0, readLength);
  482.                 }
  483.             } finally {
  484.                 if (inputStream != null) {
  485.                     try {
  486.                         inputStream.close();
  487.                     } catch (IOException ex) {
  488.                         // just ignore
  489.                     }
  490.                 }
  491.                 if (fin != null) {
  492.                     try {
  493.                         fin.close();
  494.                     } catch (IOException ex) {
  495.                         // just ignore
  496.                     }
  497.                 }
  498.             }
  499.         }
  500.         if (srcFile.isDirectory()) { // 文件夹,进行递归
  501.             File[] srcFiles = srcFile.listFiles();
  502.             for (File temp : srcFiles) {
  503.                 zipDir(temp, zipOutputStream);
  504.             }
  505.         }
  506.     }
  507.     /**
  508.      * @param args
  509.      * @throws IOException
  510.      */
  511.     public static void main(String[] args) throws IOException {
  512. //      ZipUtil z = new ZipUtil();
  513. //      // z.zipDir("d:/logs", "", true);
  514. //      // System.out.println("压缩结束");
  515. //      z.unzipDir("d:/logs.zip", true);
  516. //      System.out.println("解压缩结束");
  517.         
  518.         String sysTemp = System.getProperty("java.io.tmpdir");//获取到系统临时目录
  519.         //C:/DOCUME~1/WANGMI~1/LOCALS~1/Temp/
  520.         sysTemp = sysTemp.replace("//", "/");
  521.         ZipUtil z = new ZipUtil();
  522.         z.zipFile("d:/logs/work.log",sysTemp,System.currentTimeMillis()+""true);
  523.         System.out.println("结束");
  524.     }
  525. }
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现Java中的Zip文件压缩解压缩操作,可以使用Java提供的ZipInputStream和ZipOutputStream类。下面是一个简单的示例代码,展示如何高效地解压缩Zip文件: ```java import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class ZipUtils { public static void unzip(String zipFilePath, String destDirectory) throws IOException { File destDir = new File(destDirectory); if (!destDir.exists()) { destDir.mkdir(); } ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath)); ZipEntry entry = zipIn.getNextEntry(); while (entry != null) { String filePath = destDirectory + File.separator + entry.getName(); if (!entry.isDirectory()) { extractFile(zipIn, filePath); } else { File dir = new File(filePath); dir.mkdir(); } zipIn.closeEntry(); entry = zipIn.getNextEntry(); } zipIn.close(); } private static void extractFile(ZipInputStream zipIn, String filePath) throws IOException { BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); byte[] bytesIn = new byte[4096]; int read = 0; while ((read = zipIn.read(bytesIn)) != -1) { bos.write(bytesIn, 0, read); } bos.close(); } } ``` 示例代码中的`unzip`方法接收两个参数:`zipFilePath`表示要解压缩Zip文件的路径,`destDirectory`表示解压缩后的文件存放目录。代码首先创建目标文件夹,然后打开Zip文件并逐个读取其中的ZipEntry,如果是文件就解压缩到目标文件夹,如果是目录就创建对应的目录。解压缩过程中使用了`BufferedOutputStream`来提高效率。 要实现Zip文件的压缩,可以使用Java提供的ZipEntryZipOutputStream类。下面是一个简单的示例代码,展示如何压缩一个文件或目录为Zip文件: ```java import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipUtils { public static void zip(String sourceFile, String zipFilePath) throws IOException { FileOutputStream fos = new FileOutputStream(zipFilePath); ZipOutputStream zipOut = new ZipOutputStream(fos); File fileToZip = new File(sourceFile); zipFile(fileToZip, fileToZip.getName(), zipOut); zipOut.close(); fos.close(); } private static void zipFile(File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException { if (fileToZip.isHidden()) { return; } if (fileToZip.isDirectory()) { File[] children = fileToZip.listFiles(); for (File childFile : children) { zipFile(childFile, fileName + "/" + childFile.getName(), zipOut); } return; } FileInputStream fis = new FileInputStream(fileToZip); ZipEntry zipEntry = new ZipEntry(fileName); zipOut.putNextEntry(zipEntry); byte[] bytes = new byte[1024]; int length; while ((length = fis.read(bytes)) >= 0) { zipOut.write(bytes, 0, length); } fis.close(); } } ``` 示例代码中的`zip`方法接收两个参数:`sourceFile`表示要压缩的文件或目录的路径,`zipFilePath`表示压缩后的Zip文件路径。代码首先创建ZipOutputStream并打开输出文件,然后递归地压缩文件或目录中的所有文件,最后关闭输出流。压缩过程中使用了`FileInputStream`和`ZipEntry`来逐个读取文件并写入Zip文件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值