2009-10-07 17 views
27

Ho creato un file JAR. Ora ho creato un altro programma Java. Voglio decomprimere quel file JAR in qualche altra directory, nel senso che voglio fare qualcosa come decomprimere.Come scrivere un programma Java che può estrarre un file JAR e memorizzarne i dati nella directory specificata (posizione)?

Se corro jar -xf filename.jar questo fa sì che alcuni di errore:

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

risposta

54

adattare questo esempio: How to extract Java resources from JAR and zip archive

Oppure provare questo codice:

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

Fonte: http://www.devx.com/tips/Tip/22124

+2

Non funziona per nessun altro? Continuo a ricevere FileNotFoundExceptions a causa di questo ..... – Flafla2

+0

Lo stesso problema per me @ Flafla2. – MiJyn

+2

@lkjoel La ragione per cui si sta generando un'eccezione è perché si sta essenzialmente cercando di scrivere cose come "dest/folder1/file1" prima di aver creato "dest/folder1". Per risolvere questo problema, raccomando di eseguire iterazione preliminarmente tramite l'enumerazione JarEntry e di trasformarla in un elenco ordinato su getName(). Size() (almeno dal più grande). In questo modo, creerai tutte le directory necessarie prima di accedere ai relativi file secondari/sottodirectory. – Destin

1

Il titolo non sembra corrispondere alla domanda molto bene, ma se davvero si vuole "dare [un] programma Java l'estrazione di un file jar "hai solo bisogno di Class JarFile.

+0

sì Voglio scrivere un programma Java che estrarre un file jar –

4

JarFile classe.

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

Sì voglio qualcosa di simile, ma come posso salvare il file estratto in altre directory. Puoi per favore guidarmi. –

5

È possibile utilizzare questo frammento di codice come riferimento per ottenere il vostro compito fatto. È quasi lo stesso frammento di codice mostrato sopra da @JuanZe tranne che per quelli che erano getti ng FileNotFoundException, ho aggiunto un piccolo snippet di codice che controllerà se il file esiste e se non lo fa, creerà la cartella principale insieme ai file e estrarrà il contenuto del file jar all'interno della cartella di destinazione specificata.

Codice frammento:

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

Questo codice verrà eseguito per coloro che ottengono FileNotFound Exception nel caso precedente – stacky

2

Ecco quello che vorrei fare per estrarre tutta la mia cartella "Risorse" dal mio vaso. È molto più veloce usare BufferedReader e 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

utilizzando il lettore bufferizzato, viene eseguito in pochi secondi. Differenza enorme. Grazie –

1

È possibile utilizzare questo molto semplice libreria per pacchetto/file jar unpack

JarManager

Molto semplice

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

È inoltre possibile utilizzare Maven dipendenza

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

È inoltre necessario il mio repository

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

Controllare l'ultima versione con il collegamento muggito di utilizzare l'ultima dipendenza

Si prega di utilizzare il mio public issue tracker se trovate qualche bug

0

Beh qui è la mia versione, utilizzando 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

Vecchia domanda.
Ecco una risposta aggiornata utilizzando:

  • Java 7 java.nio per creare e copiare in modo efficiente POSTs
  • Java 8 stream per ordinare e raccogliere le voci lexicographically (al fine di sempre creato le cartelle prima).

Nota che ho utilizzato java.util.zip.ZipFile (la classe base) anziché java.util.jar.JarFile (la sottoclasse).
L'ultimo esegue più cose e questi non sono necessari per l'estrazione di file da un caso di utilizzo di archivio.
In tal modo si riduce il sovraccarico e si evita l'aumento delle eccezioni legate a problemi di sicurezza.

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

    } 
} 
Problemi correlati