2009-10-07 9 views
27

Utworzono plik JAR. Teraz stworzyłem inny program w języku Java. Chcę rozpakować ten plik JAR w innym katalogu, co oznacza, że ​​chcę zrobić coś w stylu rozpakowania.Jak napisać program w języku Java, który może wyodrębnić plik JAR i zapisać dane w określonym katalogu (lokalizacji)?

Jeśli biegnę jar -xf filename.jar Powoduje to jakiś błąd:

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)` 

Odpowiedz

54

Adapt poniższym przykładzie: How to extract Java resources from JAR and zip archive

Lub spróbuj tego kodu:

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(); 

Źródło: http://www.devx.com/tips/Tip/22124

+2

Czy to nie działa dla nikogo innego? Wciąż dostaję wyrzucane FileNotFoundExceptions z tego powodu ..... – Flafla2

+0

Ten sam problem dla mnie @ Flafla2. – MiJyn

+2

@lkjoel Powodem, dla którego rzuca wyjątek jest to, że zasadniczo próbujesz napisać takie rzeczy jak "dest/folder1/plik1" zanim utworzysz "dest/folder1". Aby rozwiązać ten problem, polecam iterację z wyliczeniem JarEntry i przekształcenie go na listę, która jest posortowana na getName(). Size() (najmniej do największego). W ten sposób utworzysz wszystkie niezbędne katalogi przed uzyskaniem dostępu do ich plików/podkatalogów podrzędnych. – Destin

1

Twój tytuł nie wydaje się, aby dopasować się pytanie bardzo dobrze, ale jeśli naprawdę chcesz „write [A] program java wyodrębnianie pliku jar "potrzebujesz tylko Class JarFile.

+0

tak chcę napisać program Java, który będzie wyodrębnić plik jar –

4

JarFile klasa.

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

Tak chcę coś takiego, ale w jaki sposób można zapisać plik wyodrębniony w innym katalogu. Czy możesz mnie poprowadzić? –

5

Można użyć tego fragmentu kodu jako punkt odniesienia, aby otrzymać zadanie done.Jest prawie taki sam jak fragment kodu pokazany powyżej przez @JuanZe z wyjątkiem tego dla tych, którzy byli getti W FileNotFoundException dodałem mały fragment kodu, który sprawdzi, czy plik istnieje, a jeśli nie, utworzy folder macierzysty wraz z plikami i wyodrębni zawartość pliku jar w określonym folderze docelowym.

Fragment kodu:

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

Ten kod snipped będzie działał dla tych, którzy uzyskują wyjątek FileNotFound w poprzednim przypadku. – stacky

2

Oto, co chciałbym zrobić, aby wydobyć całe folder „zasobów” z moim słoiku. O wiele szybciej jest używać BufferedReader i 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

Używając buforowanego czytnika, robi się to w kilka sekund. Duża różnica. Dzięki –

1

Można użyć tego bardzo prosty biblioteki opakowanie/pliku rozpakować słoik

JarManager

bardzo prosta

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()); 
} 

Można również użyć zależność maven

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

Trzeba też moim repozytorium

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

Sprawdź ostatnią wersję z linku poniżej, aby skorzystać z ostatnią zależność

Proszę używać mojego public issue tracker jeśli znajdziesz jakieś błędy

0

Więc tutaj jest mój wersja, używając 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

Stare pytanie.
Oto odpowiedź przy użyciu zaktualizowanego:

  • Java 7 java.nio do tworzenia i kopiowania skutecznie wjazdowe
  • Java 8 stream do sortowania i zbierać wpisy leksykograficznie (aby zawsze tworzone foldery pierwszy).

Zauważ, że użyłem java.util.zip.ZipFile (klasa bazowa) zamiast java.util.jar.JarFile (podklasa).
Ten ostatni wykonuje więcej rzeczy i nie są one wymagane do wyodrębniania plików z użycia w archiwum.
Zmniejsza to obciążenie i zapobiega wzrostowi wyjątków związanych z kwestiami bezpieczeństwa.

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); 
      } 
     } 

    } 
} 
Powiązane problemy