RT  网上说用org.apache.tools.zip可以解决,我用后没有效果(注释掉的部分)。代码如下,求指教import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;import java.util.zip.ZipEntry;
import java.util.Enumeration;
import java.util.zip.ZipInputStream;
import de.innosystec.unrar.Archive;
import de.innosystec.unrar.rarfile.FileHeader;
 
//import org.apache.tools.zip.ZipEntry;
//import org.apache.tools.zip.ZipFile; 
//import org.apache.tools.zip.ZipOutputStream; 
public class UnRarUtil 
{
private static void unRar(String srcRar,String destDir) throws Exception
{
Archive a =null;
FileOutputStream fos = null;
try{
a = new Archive(new File(srcRar));
FileHeader fh = a.nextFileHeader();
while(fh != null)
{
if(!fh.isDirectory())
{
//根据不同的操作系统取得相应的destFileName,destDirNamme
String compressFileName = fh.getFileNameString().trim();
String destFileName = "";
String destDirNamme = "";
//非windows操作系统
if(File.separator.equals("/"))
{
destFileName = destDir + compressFileName.replaceAll("\\\\", "/");
destDirNamme = destFileName.substring(0, destFileName.lastIndexOf("/"));
}
else//windows系统
{
destFileName = destDir + compressFileName.replaceAll("/", "\\\\");
destDirNamme = destFileName.substring(0, destFileName.lastIndexOf("\\"));
}

File dir = new File(destDirNamme);
if(!dir.exists() || !dir.isDirectory())
{
dir.mkdirs();
}

fos = new FileOutputStream(new File(destFileName));
a.extractFile(fh, fos);
fos.close();
fos = null;
}
fh = a.nextFileHeader();
}
a.close();
a = null;
}
catch(Exception e){
throw e;
}
finally{
if(fos != null)
{
try{
fos.close();
fos = null;
}
catch(Exception e){
e.printStackTrace();
}
}
if(a != null)
{
try{
a.close();
a = null;
}
catch(Exception e){
e.printStackTrace();
}
}
}
}

public static void doCompress(String srcFile,String destDir) throws Exception
{
//保证文件夹路径最后是"\"或者"/"
char lastChar = destDir.charAt(destDir.length()-1);
if(lastChar != '\\' && lastChar != '/')
{
destDir += File.separator;
}
//根据类型进行相应的解压
String type = srcFile.substring(srcFile.lastIndexOf(".")+1);
if(type.endsWith("zip"))
{
unZip(srcFile,destDir);
}
else if(type.endsWith("rar"))
{
UnRarUtil.unRar(srcFile, destDir);
}
else
{
throw new Exception("只支持zip和rar格式的压缩包!");
}
}

public static void unZip(String unZipfileName, String mDestPath) {
        if (!mDestPath.endsWith("/")) 
        {
            mDestPath = mDestPath + "/";
        }
        FileOutputStream fileOut = null;
        ZipInputStream zipIn = null;
        ZipEntry zipEntry = null;
        File file = null;
        int readedBytes = 0;
        byte buf[] = new byte[4096];
        try {
            zipIn = new ZipInputStream(new BufferedInputStream(new FileInputStream(unZipfileName)));
                        
            while ((zipEntry = zipIn.getNextEntry()) != null) 
            {
                file = new File(mDestPath + zipEntry.getName());
                if (zipEntry.isDirectory()) 
                {
                    file.mkdirs();
                } else 
                {
                    // 如果指定文件的目录不存在,则创建之.
                    File parent = file.getParentFile();
                    if (!parent.exists()) 
                    {
                        parent.mkdirs();
                    }
                    fileOut = new FileOutputStream(file);
                    while ((readedBytes = zipIn.read(buf)) > 0) 
                    {
                        fileOut.write(buf, 0, readedBytes);
                    }
                    fileOut.close();
                }
                zipIn.closeEntry();
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

//  public static void unZip(String zipfile, String destDir) 
//  {   
//        byte b[] = new byte [1024]; 
//        int length;
//        ZipFile zipFile; 
//        try { 
//
//            zipFile = new ZipFile( new File(zipfile,"GBK")); 
//
//            Enumeration<?> enumeration = zipFile.getEntries(); 
//            ZipEntry zipEntry = null ;
//            while (enumeration.hasMoreElements()) 
//            { 
//               zipEntry = (ZipEntry) enumeration.nextElement(); 
//               File loadFile = new File(destDir + zipEntry.getName()); 
//
//   
//
//               if (zipEntry.isDirectory()) { 
//
//                   // 这段都可以不要,因为每次都貌似从最底层开始遍历的 
//
//                   loadFile.mkdirs(); 
//
//               } else { 
//
//                   if (!loadFile.getParentFile().exists()) 
//
//                      loadFile.getParentFile().mkdirs(); 
//
//   
//
//                   OutputStream outputStream = new FileOutputStream(loadFile); 
//
//                   InputStream inputStream = zipFile.getInputStream(zipEntry); 
//
//   
//
//                   while ((length = inputStream.read(b)) > 0) 
//
//                      outputStream.write(b, 0, length); 
//
//   
//
//               } 
//
//            } 
//
//            System. out .println( " 文件解压成功 " ); 
//
//        } catch (IOException e) { 
//
//            // TODO Auto-generated catch block 
//
//            e.printStackTrace(); 
//
//        } 
//
//   
//
//     }  }

解决方案 »

  1.   

    我用的方法是直接复制出jdk中的那个ZipOutputStream类,然后改写下那个写入文件名的部分,具体可以谷歌百度
      

  2.   

    确认下压缩时用的是什么字符集,是不是UTF-8?
      

  3.   

    其实还是字符集问题,参考下这里解决吧:
    http://hi.baidu.com/wqj403/blog/item/b90b2537c73c7e380855a962.html
      

  4.   

    package com.*.*.server.resource.utils;import java.io.OutputStream;
    import java.io.IOException;
    import java.lang.reflect.Field;
    import java.util.Date;
    import java.util.Vector;
    import java.util.HashSet;
    import java.util.zip.CRC32;
    import java.util.zip.Deflater;
    import java.util.zip.DeflaterOutputStream;
    import java.util.zip.ZipException;/**
     * 
     *此类从JDK中复制出来,添加了对中文文件名的支持
     * 
     * @author zengj
     * @version [版本号, 2012-2-9]
     * @see [相关类/方法]
     * @since [产品/模块版本]
     */
    public class CNZipOutPutStream extends DeflaterOutputStream implements ZipConstants
    {
        
        private static class XEntry
        {
            public final ZipEntry entry;
            
            public final long offset;
            
            public final int flag;
            
            public XEntry(ZipEntry entry, long offset)
            {
                this.entry = entry;
                this.offset = offset;
                this.flag = (entry.method == DEFLATED && (entry.size == -1 || entry.csize == -1 || entry.crc == -1))
                // store size, compressed size, and crc-32 in data descriptor
                // immediately following the compressed entry data
                ? 8
                    // store size, compressed size, and crc-32 in LOC header
                    : 0;
            }
        }
        
        private XEntry current;
        
        private Vector<XEntry> xentries = new Vector<XEntry>();
        
        private HashSet<String> names = new HashSet<String>();
        
        private CRC32 crc = new CRC32();
        
        private long written = 0;
        
        private long locoff = 0;
        
        private String comment;
        
        private int method = DEFLATED;
        
        private boolean finished;
        
        private boolean closed = false;
        
        private String fileNameEncoding = "UTF-8";
        
        private static int version(ZipEntry e)
            throws ZipException
        {
            switch (e.getMethod())
            {
                case DEFLATED:
                    return 20;
                case STORED:
                    return 10;
                default:
                    throw new ZipException("unsupported compression method");
            }
        }
        
        /**
         * Checks to make sure that this stream has not been closed.
         */
        private void ensureOpen()
            throws IOException
        {
            if (closed)
            {
                throw new IOException("Stream closed");
            }
        }
        
        /**
         * Compression method for uncompressed (STORED) entries.
         */
        public static final int STORED = ZipEntry.STORED;
        
        /**
         * Compression method for compressed (DEFLATED) entries.
         */
        public static final int DEFLATED = ZipEntry.DEFLATED;
        
        /**
         * Creates a new ZIP output stream.
         * 
         * @param out the actual output stream
         */
        public CNZipOutPutStream(OutputStream out)
        {
            super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
            try
            {
                Field f = this.getClass().getDeclaredField("usesDefaultDeflater");
                f.setAccessible(true);
                f.set(this, true);
            }
            catch (NoSuchFieldException e)
            { // Ignore
            }
            catch (IllegalAccessException e)
            {// Ignore
            }
        }
        
        /**
         *此方法扩展了JDK的ZIP压缩输出流的默认构造函数,添加了一个内部文件名编码参数
         */
        public CNZipOutPutStream(OutputStream out, String fileNameEncoding)
        {
            this(out);
            if (fileNameEncoding != null)
            {
                this.fileNameEncoding = fileNameEncoding;
            }
        }
     
       
      

  5.   

       
        /**
         * Sets the ZIP file comment.
         * 
         * @param comment the comment string
         * @exception IllegalArgumentException if the length of the specified ZIP file comment is greater than 0xFFFF bytes
         */
        public void setComment(String comment)
        {
            if (comment != null && comment.length() > 0xffff / 3 && getUTF8Length(comment) > 0xffff)
            {
                throw new IllegalArgumentException("ZIP file comment too long.");
            }
            this.comment = comment;
        }
        
        /**
         * Sets the default compression method for subsequent entries. This default will be used whenever the compression
         * method is not specified for an individual ZIP file entry, and is initially set to DEFLATED.
         * 
         * @param method the default compression method
         * @exception IllegalArgumentException if the specified compression method is invalid
         */
        public void setMethod(int method)
        {
            if (method != DEFLATED && method != STORED)
            {
                throw new IllegalArgumentException("invalid compression method");
            }
            this.method = method;
        }
        
        /**
         * Sets the compression level for subsequent entries which are DEFLATED. The default setting is DEFAULT_COMPRESSION.
         * 
         * @param level the compression level (0-9)
         * @exception IllegalArgumentException if the compression level is invalid
         */
        public void setLevel(int level)
        {
            def.setLevel(level);
        }
      
      

  6.   

      
        /**
         * Begins writing a new ZIP file entry and positions the stream to the start of the entry data. Closes the current
         * entry if still active. The default compression method will be used if no compression method was specified for the
         * entry, and the current time will be used if the entry has no set modification time.
         * 
         * @param e the ZIP entry to be written
         * @exception ZipException if a ZIP format error has occurred
         * @exception IOException if an I/O error has occurred
         */
        public void putNextEntry(ZipEntry e)
            throws IOException
        {
            ensureOpen();
            if (current != null)
            {
                closeEntry(); // close previous entry
            }
            if (e.time == -1)
            {
                e.setTime(System.currentTimeMillis());
            }
            if (e.method == -1)
            {
                e.method = method; // use default method
            }
            switch (e.method)
            {
                case DEFLATED:
                    break;
                case STORED:
                    // compressed size, uncompressed size, and crc-32 must all be
                    // set for entries using STORED compression method
                    if (e.size == -1)
                    {
                        e.size = e.csize;
                    }
                    else if (e.csize == -1)
                    {
                        e.csize = e.size;
                    }
                    else if (e.size != e.csize)
                    {
                        throw new ZipException("STORED entry where compressed != uncompressed size");
                    }
                    if (e.size == -1 || e.crc == -1)
                    {
                        throw new ZipException("STORED entry missing size, compressed size, or crc-32");
                    }
                    break;
                default:
                    throw new ZipException("unsupported compression method");
            }
            if (!names.add(e.name))
            {
                throw new ZipException("duplicate entry: " + e.name);
            }
            current = new XEntry(e, written);
            xentries.add(current);
            writeLOC(current);
        }
        
        /**
         * Closes the current ZIP entry and positions the stream for writing the next entry.
         * 
         * @exception ZipException if a ZIP format error has occurred
         * @exception IOException if an I/O error has occurred
         */
        public void closeEntry()
            throws IOException
        {
            ensureOpen();
            if (current != null)
            {
                ZipEntry e = current.entry;
                switch (e.method)
                {
                    case DEFLATED:
                        def.finish();
                        while (!def.finished())
                        {
                            deflate();
                        }
                        if ((current.flag & 8) == 0)
                        {
                            // verify size, compressed size, and crc-32 settings
                            if (e.size != def.getBytesRead())
                            {
                                throw new ZipException("invalid entry size (expected " + e.size + " but got "
                                    + def.getBytesRead() + " bytes)");
                            }
                            if (e.csize != def.getBytesWritten())
                            {
                                throw new ZipException("invalid entry compressed size (expected " + e.csize + " but got "
                                    + def.getBytesWritten() + " bytes)");
                            }
                            if (e.crc != crc.getValue())
                            {
                                throw new ZipException("invalid entry CRC-32 (expected 0x" + Long.toHexString(e.crc)
                                    + " but got 0x" + 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;
                    case STORED:
                        // we already know that both e.size and e.csize are the same
                        if (e.size != written - locoff)
                        {
                            throw new ZipException("invalid entry size (expected " + e.size + " but got "
                                + (written - locoff) + " bytes)");
                        }
                        if (e.crc != crc.getValue())
                        {
                            throw new ZipException("invalid entry crc-32 (expected 0x" + Long.toHexString(e.crc)
                                + " but got 0x" + Long.toHexString(crc.getValue()) + ")");
                        }
                        break;
                    default:
                        throw new ZipException("invalid compression method");
                }
                crc.reset();
                current = null;
            }
        }
         /**
         * Writes an array of bytes to the current ZIP entry data. This method will block until all the bytes are written.
         * 
         * @param b the data to be written
         * @param off the start offset in the data
         * @param len the number of bytes that are written
         * @exception ZipException if a ZIP file error has occurred
         * @exception IOException if an I/O error has occurred
         */
        public synchronized void write(byte[] b, int off, int len)
            throws IOException
        {
            ensureOpen();
            if (off < 0 || len < 0 || off > b.length - len)
            {
                throw new IndexOutOfBoundsException();
            }
            else if (len == 0)
            {
                return;
            }
            
            if (current == null)
            {
                throw new ZipException("no current ZIP entry");
            }
            ZipEntry entry = current.entry;
            switch (entry.method)
            {
                case DEFLATED:
                    super.write(b, off, len);
                    break;
                case STORED:
                    written += len;
                    if (written - locoff > entry.size)
                    {
                        throw new ZipException("attempt to write past end of STORED entry");
                    }
                    out.write(b, off, len);
                    break;
                default:
                    throw new ZipException("invalid compression method");
            }
            crc.update(b, off, len);
        }
        
        /**
         * Finishes writing the contents of the ZIP output stream without closing the underlying stream. Use this method
         * when applying multiple filters in succession to the same output stream.
         * 
         * @exception ZipException if a ZIP file error has occurred
         * @exception IOException if an I/O exception has occurred
         */
        public void finish()
            throws IOException
        {
            ensureOpen();
            if (finished)
            {
                return;
            }
            if (current != null)
            {
                closeEntry();
            }
            if (xentries.size() < 1)
            {
                throw new ZipException("ZIP file must have at least one entry");
            }
            // write central directory
            long off = written;
            for (XEntry xentry : xentries)
                writeCEN(xentry);
            writeEND(off, written - off);
            finished = true;
        }
        
        /**
         * Closes the ZIP output stream as well as the stream being filtered.
         * 
         * @exception ZipException if a ZIP file error has occurred
         * @exception IOException if an I/O error has occurred
         */
        public void close()
            throws IOException
        {
            if (!closed)
            {
                super.close();
                closed = true;
            }
        }
        
        /*
         * Writes local file (LOC) header for specified entry.
         */
        private void writeLOC(XEntry xentry)
            throws IOException
        {
            ZipEntry e = xentry.entry;
            int flag = xentry.flag;
            writeInt(LOCSIG); // LOC header signature
            writeShort(version(e)); // version needed to extract
            writeShort(flag); // general purpose bit flag
            writeShort(e.method); // compression method
            writeInt(e.time); // last modification time
            if ((flag & 8) == 8)
            {
                // store size, uncompressed size, and crc-32 in data descriptor
                // immediately following compressed entry data
                writeInt(0);
                writeInt(0);
                writeInt(0);
            }
            else
            {
                writeInt(e.crc); // crc-32
                writeInt(e.csize); // compressed size
                writeInt(e.size); // uncompressed size
            }
            byte[] nameBytes = null;
            if ("UTF-8".equalsIgnoreCase(fileNameEncoding))
            {
                nameBytes = getUTF8Bytes(e.name);
            }
            else
            {
                nameBytes = e.name.getBytes(fileNameEncoding);
            }
            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;
        }
        
        /*
         * Writes extra data descriptor (EXT) for specified entry.
         */
        private void writeEXT(ZipEntry e)
            throws IOException
        {
            writeInt(EXTSIG); // EXT header signature
            writeInt(e.crc); // crc-32
            writeInt(e.csize); // compressed size
            writeInt(e.size); // uncompressed size
        }