2012-07-11 18 views
6

Tôi đang sử dụng thư viện Apache Commons 1.4.1 để nén và giải nén các tệp ".tar.gz".Cách gỡ bỏ tệp TAR bằng cách sử dụng Apache Commons

Tôi đang gặp sự cố với bit cuối cùng - chuyển đổi TarArchiveInputStream thành FileOutputStream.

Lạ lùng thay, nó phá vỡ vào dòng này:

FileOutputStream fout = new FileOutputStream(destPath); 

destPath là một tập tin với một con đường Canonical của: C: \ Documents and Settings \ Administrator \ My Documents \ JavaWorkspace \ BackupUtility \ untarred \ Test \ subdir \ testinsub.txt

Lỗi sản xuất:

Exception in thread "main" java.io.IOException: The system cannot find the path specified 

Bất kỳ ý tưởng nó có thể là gì? Và tại sao nó không thể tìm ra con đường?

Tôi đang đính kèm toàn bộ phương pháp bên dưới (hầu hết trong số đó được gỡ bỏ từ here).

private void untar(File dest) throws IOException { 
    dest.mkdir(); 
    TarArchiveEntry tarEntry = tarIn.getNextTarEntry(); 
    // tarIn is a TarArchiveInputStream 
    while (tarEntry != null) {// create a file with the same name as the tarEntry 
     File destPath = new File(dest.toString() + System.getProperty("file.separator") + tarEntry.getName()); 
     System.out.println("working: " + destPath.getCanonicalPath()); 
     if (tarEntry.isDirectory()) { 
      destPath.mkdirs(); 
     } else { 
      destPath.createNewFile(); 
      FileOutputStream fout = new FileOutputStream(destPath); 
      tarIn.read(new byte[(int) tarEntry.getSize()]); 
      fout.close(); 
     } 
     tarEntry = tarIn.getNextTarEntry(); 
    } 
    tarIn.close(); 
} 
+0

Xấu hổ khi hỏi điều này, nhưng tôi đã thử sử dụng mẫu mã của bạn và thấy nó hoạt động với một tệp 'gzip' cụ thể mà tôi đang làm việc. Làm thế nào nó hoạt động mà không có bất kỳ cuộc gọi đến 'fout.write (...)' cho nội dung đọc trên inputStream? Trong [answer @ user1894600 gợi ý] (http://stackoverflow.com/a/14211580/320399), anh ta phải gọi 'write (...)' và cung cấp mảng byte đã được đọc vào bộ nhớ. – blong

Trả lời

5

Một vài điểm chung, tại sao bạn làm voodoo với các nhà xây dựng File, nơi có một perfectly usable constructor nơi bạn có thể xác định tên của File bạn muốn tạo và đưa ra một tập tin cha mẹ?

Thứ hai, tôi không chắc chắn cách các khoảng trống được xử lý trong đường dẫn trong cửa sổ. Nó có thể là nguyên nhân của vấn đề của bạn. Hãy thử sử dụng các nhà xây dựng tôi đã đề cập ở trên và xem nếu nó làm cho một sự khác biệt:. File destPath = new File(dest, tarEntry.getName()); (giả định rằng File dest là một hồ sơ hợp lệ, và tồn tại và có thể truy cập bởi bạn

Thứ ba, trước khi bạn làm bất cứ điều gì với một đối tượng File bạn nên kiểm tra nếu nó tồn tại và nếu nó có thể truy cập. đó là cuối cùng sẽ giúp bạn xác định được vấn đề.

+0

Cảm ơn bạn đã trả lời. Tôi đã quyết định viết lại module và nó hoạt động rất tốt. Tôi đã đưa ra lời khuyên của bạn về việc không chơi với đối tượng File, và vì vậy tôi sẽ đánh dấu câu trả lời của bạn là câu trả lời đúng (dựa trên nguyên tắc) – Redandwhite

+0

Vui vì nó đã giúp, và hy vọng tất cả đều hoạt động tốt đẹp cuối cùng. Chúc may mắn :) – posdef

+0

Tôi đang sử dụng cùng một mã để gỡ bỏ một tệp .tar không phải là .tar.gz. Và tôi nhận được từ dòng này 'new File (dest, tarEntry.getName())' nội dung tập tin không phải là tên tập tin. Những gì tôi có thể làm để có được tên tập tin bên trong .tar –

13

chương trình của bạn có lỗi java không gian heap. vì vậy tôi nghĩ một chút thay đổi cần thiết. đây là mã ...

public static void uncompressTarGZ(File tarFile, File dest) throws IOException { 
    dest.mkdir(); 
    TarArchiveInputStream tarIn = null; 

    tarIn = new TarArchiveInputStream(
       new GzipCompressorInputStream(
        new BufferedInputStream(
         new FileInputStream(
          tarFile 
         ) 
        ) 
       ) 
      ); 

    TarArchiveEntry tarEntry = tarIn.getNextTarEntry(); 
    // tarIn is a TarArchiveInputStream 
    while (tarEntry != null) {// create a file with the same name as the tarEntry 
     File destPath = new File(dest, tarEntry.getName()); 
     System.out.println("working: " + destPath.getCanonicalPath()); 
     if (tarEntry.isDirectory()) { 
      destPath.mkdirs(); 
     } else { 
      destPath.createNewFile(); 
      //byte [] btoRead = new byte[(int)tarEntry.getSize()]; 
      byte [] btoRead = new byte[1024]; 
      //FileInputStream fin 
      // = new FileInputStream(destPath.getCanonicalPath()); 
      BufferedOutputStream bout = 
       new BufferedOutputStream(new FileOutputStream(destPath)); 
      int len = 0; 

      while((len = tarIn.read(btoRead)) != -1) 
      { 
       bout.write(btoRead,0,len); 
      } 

      bout.close(); 
      btoRead = null; 

     } 
     tarEntry = tarIn.getNextTarEntry(); 
    } 
    tarIn.close(); 
} 

good l ─

+0

Vì vậy, lỗi không gian đống sẽ xảy ra vì mảng byte có khả năng quá lớn khi nó được khai báo là 'byte [] btoRead = new byte [(int) tarEntry.getSize() ]; '? – blong

+1

Phản hồi tuyệt vời. Tuy nhiên, 'deskPath.createNewFile();' sẽ được sửa đổi để tạo thư mục cha 'if (! DestPath.getParentFile().tồn tại()) { destPath.getParentFile(). mkdirs(); } destPath.createNewFile(); ' –