天天看點

java 處理zip 壓縮與解壓的問題

今天項目中遇到zip檔案的壓縮與解壓問題。處理的是壓縮和解壓多級目錄的問題。

廢話不說把代碼先貼上。

/**
     * 建立ZIP檔案
     * @author 小馬
     * @creaetime 2013年12月9日 下午4:30:37
     * @param sourcePath 檔案或檔案夾路徑
     * @param zipPath 生成的zip檔案存在路徑(包括檔案名)
     */
    public boolean createZip(String sourcePath, String zipPath) {
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        File file = null;
        boolean result = false;
        try {
            fos = new FileOutputStream(zipPath);
            zos = new ZipOutputStream(fos);
            file = new File(sourcePath);
            result = writeZip(file, "", zos);
        }
        catch (FileNotFoundException e) {
            result = false;
        }
        finally {
            try {
                if ( zos != null ) {
                    zos.close();
                }
//                del(sourcePath);
            }
            catch (IOException e) {
                result = false;
            }
        }
       return result;
    }

    /**
     * @author 小馬
     * @creaetime 2013年12月9日 下午4:30:30
     * @param file
     * @param parentPath
     * @param zos
     */
    private boolean writeZip(File file, String parentPath, ZipOutputStream zos) {
        boolean flag = true;
        if ( file.exists() ) {
            if ( file.isDirectory() ) {// 處理檔案夾
                parentPath += file.getName() + File.separator;
                File[] files = file.listFiles();
                for (File f : files) {
                    writeZip(f, parentPath, zos);
                }
            }
            else {
                FileInputStream fis = null;
                try {
                    fis = new FileInputStream(file);
                    ZipEntry ze = new ZipEntry(parentPath + file.getName());
                    zos.putNextEntry(ze);
                    byte[] content = new byte[1024];
                    int len;
                    while ((len = fis.read(content)) != -1) {
                        zos.write(content, 0, len);
                        zos.flush();
                    }

                }
                catch (FileNotFoundException e) {
                    flag = false;
                }
                catch (IOException e) {
                    flag = false;
                }
                finally {
                    try {
                        if ( fis != null ) {
                            fis.close();
                        }
                    }
                    catch (IOException e) {
                        flag = false;
                    }
                }
            }
        }
        return flag;
    }
           

以上是檔案的壓縮方法,需要用到java.util.zip.*這個包。但是處了解壓過程中一直遇到中文亂碼問題,就是當檔案後者目錄為中文的時候,程式要報異常。

最後在網上找到了解決的方法,代碼如下:

/**
     * 解壓zip
     * @author 小馬
     * @creaetime 2013年12月11日 下午5:20:50
     * @param path 要解壓檔案
     * @param savepath 檔案解壓後儲存的目錄
     */
    public static void unZip(String path, String savepath) {
        int count = -1;
        File file = null;
        InputStream is = null;
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;

        //如果儲存目錄不存在則建立
        if ( !new File(savepath).exists() ) {
            new File(savepath).mkdir(); 
        }
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(path, "gbk"); // 解決中文亂碼問題
            Enumeration<?> entries = zipFile.getEntries();

            while (entries.hasMoreElements()) {
                byte buf[] = new byte[1024];

                ZipEntry entry = (ZipEntry) entries.nextElement();

                String filename = entry.getName();
                boolean ismkdir = false;
                if ( filename.lastIndexOf("/") != -1 ) { // 檢查此檔案是否帶有檔案夾
                    ismkdir = true;
                }
                filename = savepath + filename;

                if ( entry.isDirectory() ) { // 如果是檔案夾先建立
                    file = new File(filename);
                    file.mkdirs();
                    continue;
                }
                file = new File(filename);
                if ( !file.exists() ) { // 如果是目錄先建立
                    if ( ismkdir ) {
                        new File(filename.substring(0, filename.lastIndexOf("/"))).mkdirs(); // 目錄先建立
                    }
                }
                file.createNewFile(); // 建立檔案

                is = zipFile.getInputStream(entry);
                fos = new FileOutputStream(file);
                bos = new BufferedOutputStream(fos, 1024);

                while ((count = is.read(buf)) > -1) {
                    bos.write(buf, 0, count);
                }
                bos.flush();
                bos.close();
                fos.close();

                is.close();
            }

            zipFile.close();

        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
        finally {
            try {
                if ( bos != null ) {
                    bos.close();
                }
                if ( fos != null ) {
                    fos.close();
                }
                if ( is != null ) {
                    is.close();
                }
                if ( zipFile != null ) {
                    zipFile.close();
                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
           

解壓方法,需要用com.springsource.org.apache.tools.ant.jar 這個包,問題解決。但是在解壓原始的zip沒有問題,在解壓自己壓縮的zip則報出找不到目錄的錯誤,經過不斷折騰,斷點調試,發現 原始的zip中 String filename = entry.getName();  filename路徑是以“/”隔開,而自己壓縮的zip中,filename的路徑是以“\”隔開,于是改成String filename = entry.getName().replace("\\", "/");問題就解決了。

發現壓縮後的檔案仍有亂碼,于是壓縮方法也用org.apache.tools.zip這個包。

上代碼:

/**
     * 壓縮成zip
     * @author 小馬
     * @creaetime 2013年12月12日 上午11:39:58
     * @param zipFilep 壓縮後的zip檔案名
     * @param path 壓縮路徑
     * @throws Exception
     */
    public boolean createZip(String path, String zipFilep) {
        System.out.println("備份檔案開始.....................");
        File zipFile = new File(zipFilep);
        boolean result = false;
        ZipOutputStream out = null;
        try {
            if ( !zipFile.exists() ) {
                zipFile.createNewFile();
            }
            out = new ZipOutputStream(new FileOutputStream(zipFile));
            out.setEncoding("gbk");
            write(out, path, "");
            result = true;
        }
        catch (Exception e) {
            result = false;
        }finally{
            if(out!=null){
                try {
                    out.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("備份檔案結束.....................");
        return result;
    }

    /**
     * 寫壓縮流
     * @author 小馬
     * @creaetime 2013年12月12日 上午11:40:42
     * @param out 壓縮輸出流
     * @param path 壓縮路徑
     * @param base 壓縮式的基礎目錄 預設為空
     * @throws Exception
     */
    private void write(ZipOutputStream out, String path, String base) throws Exception {
        File file = new File(path);
        if ( file.isDirectory() ) {// 檔案夾,遞歸
            base = base.length() == 0 ? "" : base + File.separator;
            File[] tempFiles = file.listFiles();
            for (int i = 0; i < tempFiles.length; i++) {
                write(out, tempFiles[i].getPath(), base + tempFiles[i].getName());
            }
        }
        else {// 檔案,壓縮
            byte[] buff = new byte[2048];
            int bytesRead = -1;
            ZipEntry entry = new ZipEntry(base);
            out.putNextEntry(entry);
            InputStream in = new BufferedInputStream(new FileInputStream(file));
            while (-1 != (bytesRead = in.read(buff, 0, buff.length))) {
                out.write(buff, 0, bytesRead);
            }
            in.close();
            out.flush();
        }
    }