2017-04-10 140 views
1

我有解壓縮文件到子文件夾的問題。我需要解壓的zip文件有多個文件夾,我試圖在解壓縮時保持目錄結構。Java:解壓縮文件夾與子文件夾

package components; 

import java.io.BufferedOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipInputStream; 

/** 
* This utility extracts files and directories of a standard zip file to 
* a destination directory. 
* 
* 
*/ 
public class UnzipUtility { 
    /** 
    * Size of the buffer to read/write data 
    */ 
    private static final int BUFFER_SIZE = 4096; 
    /** 
    * Extracts a zip file specified by the zipFilePath to a directory specified by 
    * destDirectory (will be created if does not exists) 
    * @param zipFilePath 
    * @param destDirectory 
    * @throws IOException 
    */ 
    public 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(); 
     // iterates over entries in the zip file 
     while (entry != null) { 
      String filePath = destDirectory + File.separator + entry.getName(); 
      if (!entry.isDirectory()) { 
       // if the entry is a file, extracts it 
       extractFile(zipIn, filePath); 
       System.out.println(filePath); 
      } else { 
       // if the entry is a directory, make the directory 
       File dir = new File(filePath); 
       System.out.println(filePath); 
       dir.mkdir(); 
      } 
      zipIn.closeEntry(); 
      entry = zipIn.getNextEntry(); 
     } 
     zipIn.close(); 
    } 
    /** 
    * Extracts a zip entry (file entry) 
    * @param zipIn 
    * @param filePath 
    * @throws IOException 
    */ 
    private void extractFile(ZipInputStream zipIn, String filePath) throws IOException { 
     BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); 
     byte[] bytesIn = new byte[BUFFER_SIZE]; 
     int read = 0; 
     while ((read = zipIn.read(bytesIn)) != -1) { 
      bos.write(bytesIn, 0, read); 
     } 
     bos.close(); 
    } 
} 

我從代碼得到的輸出如下。問題在於DoD-DISA-logos-as-JPEG.jpg文件是子文件夾子文件夾的一部分。所以路徑應該是文件夾/子文件夾/子文件夾/ DoD-DISA-logos-as-JPEG.jpg。它不包括該子文件夾,所以它會得到我認爲的IO異常。

java.io.FileNotFoundException: /Users/user/Desktop/folder/subfolder/DoD-DISA-logos-as-JPEG.jpg (No such file or directory) 
    at java.io.FileOutputStream.open0(Native Method) 
    at java.io.FileOutputStream.open(FileOutputStream.java:270) 
    at java.io.FileOutputStream.<init>(FileOutputStream.java:213) 
    at java.io.FileOutputStream.<init>(FileOutputStream.java:101) 
    at components.UnzipUtility.extractFile(UnzipUtility.java:62) 
    at components.UnzipUtility.unzip(UnzipUtility.java:42) 
    at components.UnzipUtilityTest.main(UnzipUtilityTest.java:9) 
+1

'String filePath = destDirectory + File.separator + entry.getName();'路徑是否存在?如果第一個條目是一個文件,那麼你不是用'dir.mkdir'創建目錄。 – Flikk

回答

2

你不應該依賴entry.isDirectory()或對事實ZipEntry迭代器將列出所有的文件夾層次。

一個zip文件結構可能只包含一個ZipEntry文件,它的名字中包含一個子文件夾層次結構。例如。 foo/bar/file.txt將是一個ZipEntry但不foo/也不foo/bar/

因此爲:

  • 一個文件,你應該得到的父目錄,並創建整個層次,如果不File#mkdirs
  • 存在一個目錄吧,你應該創建整個層次,如果它不存在與File#mkdirs

你的代碼應該被轉換成東西IKE說:

 if (!entry.isDirectory()) { 
      // if the entry is a file, extracts it 
      new File(filePath).getParentFile().mkdirs(); 
      extractFile(zipIn, filePath); 
      System.out.println(filePath); 
     } else { 
      // if the entry is a directory, make the directory 
      File dir = new File(filePath); 
      System.out.println(filePath); 
      dir.mkdirs(); 
     } 

我建議使用一個外部庫,壓縮/解壓縮像zt-zip

+0

Nicolas,謝謝。這對我而言非常有效,而且很有教育意義。 – InTheShell

+0

不客氣! –

+1

我也推薦Apache Commons Compress用於存檔操作(https://commons.apache.org/proper/commons-compress/index.html) – fandango