2009-10-07 18 views
27

Tôi đã tạo một tệp JAR. Bây giờ, tôi đã tạo một chương trình Java khác. Tôi muốn giải nén tệp JAR đó trong một số thư mục khác, có nghĩa là tôi muốn làm một cái gì đó như giải nén.Làm thế nào để viết một chương trình Java có thể trích xuất một tệp JAR và lưu trữ dữ liệu của nó trong thư mục được chỉ định (vị trí)?

Nếu tôi chạy jar -xf filename.jar điều này gây ra một số lỗi:

Exception in thread "main" java.io.IOException: Cannot run program "jar": 
java.io.IOException: error=2, No such file or directory 
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:459) 
    at java.lang.Runtime.exec(Runtime.java:593)` 

Trả lời

54

Thích ứng ví dụ này: How to extract Java resources from JAR and zip archive

Hoặc thử mã này:

Extract the Contents of ZIP/JAR Files Programmatically

Suppose jarFile is the jar/zip file to be extracted. destDir is the path where it will be extracted:

java.util.jar.JarFile jar = new java.util.jar.JarFile(jarFile); 
java.util.Enumeration enumEntries = jar.entries(); 
while (enumEntries.hasMoreElements()) { 
    java.util.jar.JarEntry file = (java.util.jar.JarEntry) enumEntries.nextElement(); 
    java.io.File f = new java.io.File(destDir + java.io.File.separator + file.getName()); 
    if (file.isDirectory()) { // if its a directory, create it 
     f.mkdir(); 
     continue; 
    } 
    java.io.InputStream is = jar.getInputStream(file); // get the input stream 
    java.io.FileOutputStream fos = new java.io.FileOutputStream(f); 
    while (is.available() > 0) { // write contents of 'is' to 'fos' 
     fos.write(is.read()); 
    } 
    fos.close(); 
    is.close(); 
} 
jar.close(); 

Nguồn: http://www.devx.com/tips/Tip/22124

+2

Điều này có hiệu quả với bất kỳ ai khác không? Tôi tiếp tục nhận được FileNotFoundExceptions ném vì điều này ..... – Flafla2

+0

Cùng một vấn đề đối với tôi @ Flafla2. – MiJyn

+2

@ lkjoel Lý do mà nó ném một ngoại lệ là bởi vì bạn đang cố gắng để viết các công cụ như "dest/folder1/file1" trước khi bạn đã tạo ra "dest/folder1". Để giải quyết điều này, tôi khuyên bạn nên lặp lại thông qua các liệt kê JarEntry trước, và biến nó thành một danh sách được sắp xếp trên getName(). Size() (ít nhất là lớn nhất). Bằng cách đó, bạn sẽ tạo tất cả các thư mục cần thiết trước khi đến các tệp con/thư mục con của chúng. – Destin

1

Tiêu đề của bạn dường như không phù hợp với câu hỏi rất tốt nhưng nếu bạn thực sự muốn "viết [a] Chương trình java giải nén một file jar "bạn chỉ cần Class JarFile.

+0

có tôi muốn viết chương trình java sẽ trích xuất tệp jar –

4

JarFile lớp học.

JarFile file = new JarFile("file.jar"); 
for (Enumeration<JarEntry> enum = file.entries(); enum.hasMoreElements();) { 
    JarEntry entry = enum.next(); 
    System.out.println(entry.getName()); 
} 
+0

Có Tôi muốn một cái gì đó như thế này nhưng làm cách nào tôi có thể lưu trữ tệp được trích xuất trong một số thư mục khác. bạn có thể vui lòng hướng dẫn cho tôi. –

5

Bạn có thể sử dụng đoạn mã này như một tài liệu tham khảo để có được nhiệm vụ của bạn done.Its gần như giống như đoạn mã được hiển thị ở trên bởi @JuanZe ngoại trừ cho những người đã được getti ng FileNotFoundException, tôi đã thêm một đoạn mã nhỏ để kiểm tra xem tệp có tồn tại không và nếu không thì nó sẽ tạo thư mục cha cùng với các tệp và sẽ trích xuất nội dung của tệp jar bên trong thư mục đích đã chỉ định.

Đoạn mã:

public class JarDemo { 

    public static void main(String[] args) throws java.io.IOException { 
    java.util.jar.JarFile jarfile = new java.util.jar.JarFile(new java.io.File("E:/sqljdbc4.jar")); //jar file path(here sqljdbc4.jar) 
    java.util.Enumeration<java.util.jar.JarEntry> enu= jarfile.entries(); 
    while(enu.hasMoreElements()) 
    { 
     String destdir = "E:/abc/";  //abc is my destination directory 
     java.util.jar.JarEntry je = enu.nextElement(); 

     System.out.println(je.getName()); 

     java.io.File fl = new java.io.File(destdir, je.getName()); 
     if(!fl.exists()) 
     { 
      fl.getParentFile().mkdirs(); 
      fl = new java.io.File(destdir, je.getName()); 
     } 
     if(je.isDirectory()) 
     { 
      continue; 
     } 
     java.io.InputStream is = jarfile.getInputStream(je); 
     java.io.FileOutputStream fo = new java.io.FileOutputStream(fl); 
     while(is.available()>0) 
     { 
      fo.write(is.read()); 
     } 
     fo.close(); 
     is.close(); 
    } 

    } 

} 
+0

Đoạn mã này sẽ hoạt động đối với những người đang nhận ngoại lệ FileNotFound trong trường hợp trước – stacky

2

Dưới đây là những gì tôi sẽ làm gì để giải nén "tài nguyên" toàn bộ của tôi thư mục từ jar của tôi. Đó là cách nhanh hơn để sử dụng BufferedReader và BufferedWriter.

public static boolean extractResourcesToTempFolder() { 
    try { 
     //If folder exist, delete it. 
     String destPath = getTempDir() + File.separator + "JToolkit" + File.separator; 
     deleteDirectoryRecursive(new File(destPath));    

     JarFile jarFile = new JarFile(JToolkit.class.getProtectionDomain().getCodeSource().getLocation().getPath()); 
     Enumeration<JarEntry> enums = jarFile.entries(); 
     while (enums.hasMoreElements()) { 
      JarEntry entry = enums.nextElement(); 
      if (entry.getName().startsWith("resources")) { 
       File toWrite = new File(destPath + entry.getName()); 
       if (entry.isDirectory()) { 
        toWrite.mkdirs(); 
        continue; 
       } 
       InputStream in = new BufferedInputStream(jarFile.getInputStream(entry)); 
       OutputStream out = new BufferedOutputStream(new FileOutputStream(toWrite)); 
       byte[] buffer = new byte[2048]; 
       for (;;) { 
        int nBytes = in.read(buffer); 
        if (nBytes <= 0) { 
         break; 
        } 
        out.write(buffer, 0, nBytes); 
       } 
       out.flush(); 
       out.close(); 
       in.close(); 
      } 
      System.out.println(entry.getName()); 
     } 
    } catch (IOException ex) { 
     Logger.getLogger(Methods.class.getName()).log(Level.SEVERE, null, ex); 
     return false; 
    } 
    return true; 
} 
+0

Sử dụng trình đọc được đệm, nó được thực hiện trong vài giây. Sự khác biệt lớn. Cảm ơn –

1

Bạn có thể sử dụng thư viện rất đơn giản này để gói/giải nén file jar

JarManager

Rất đơn giản

import java.io.File; 
import java.util.List; 

import fr.stevecohen.jarmanager.JarUnpacker; 

class Test { 
    JarUnpacker jarUnpacker = new JarUnpacker(); 
    File myfile = new File("./myfile.jar"); 
    File unpackDir = new File("./mydir"); 

    List<File> unpacked_files = jarUnpacker.unpack(myfile.getAbsolutePath(), unpackDir.getAbsolutePath()); 
} 

Bạn cũng có thể sử dụng phụ thuộc maven

<dependency> 
    <groupId>fr.stevecohen.jarmanager</groupId> 
    <artifactId>JarManager</artifactId> 
    <version>0.5.0</version> 
</dependency> 

Bạn cũng cần kho của tôi

<repository> 
    <id>repo-reapersoon</id> 
    <name>ReaperSoon's repo</name> 
    <url>http://repo-maven.stevecohen.fr</url> 
</repository> 

Kiểm tra phiên bản mới nhất với các liên kết dưới đây để sử dụng phụ thuộc ngoái

Vui lòng sử dụng tôi public issue tracker nếu bạn tìm thấy một số lỗi

0

Vâng đây là của tôi phiên bản, sử dụng try-with-resources:

try (JarFile jarFile = new JarFile(artifact.getFile())) { 
     for (JarEntry entry : Collections.list(jarFile.entries())) { 
      try (InputStream is = jarFile.getInputStream(entry)) { 
       File file = new File(targetDir, entry.getName()); 
       try (FileOutputStream fos = new FileOutputStream(file)) { 
        fos.write(is.read()); 
       } 
      } 
     } 
    } catch (IOException e) { 
     throw new MyException(String.format(
      "Unable to open jar %s", artifact.getArtifactId()), e); 
    } 
0

Câu hỏi cũ.
Đây là một câu trả lời được cập nhật sử dụng:

  • Java 7 java.nio để tạo ra và sao chép một cách hiệu quả các entry
  • Java 8 stream để sắp xếp và thu thập các mục thứ tự từ điển (để luôn tạo ra các thư mục đầu tiên).

Lưu ý rằng tôi đã sử dụng java.util.zip.ZipFile (lớp cơ sở) thay vì java.util.jar.JarFile (lớp con).
Người cuối cùng thực hiện nhiều việc hơn và những điều này không bắt buộc đối với việc trích xuất tệp từ một trường hợp sử dụng lưu trữ.
Vì vậy, nó làm giảm chi phí và ngăn chặn sự gia tăng ngoại lệ liên quan đến mối quan tâm về bảo mật.

import java.io.IOException; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.util.List; 
import java.util.stream.Collectors; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipFile; 

public class FileUtils { 

    public static void extractArchive(Path archiveFile, Path destPath) throws IOException { 

     Files.createDirectories(destPath); // create dest path folder(s) 

     try (ZipFile archive = new ZipFile(archiveFile.toFile())) { 

      // sort entries by name to always created folders first 
      List<? extends ZipEntry> entries = archive.stream() 
                 .sorted((a, b) -> a.getName() 
                     .compareTo(b.getName())) 
                 .collect(Collectors.toList()); 

      // copy each entry in the dest path 
      for (ZipEntry entry : entries) { 
       Path entryDest = destPath.resolve(entry.getName()); 

       if (entry.isDirectory()) { 
        Files.createDirectory(entryDest); 
        continue; 
       } 

       Files.copy(archive.getInputStream(entry), entryDest); 
      } 
     } 

    } 
} 
Các vấn đề liên quan