2009-10-07 11 views
27

He creado un archivo JAR. Ahora, creé otro programa Java. Quiero descomprimir ese archivo JAR en otro directorio, lo que significa que quiero hacer algo como descomprimir.¿Cómo escribir un programa Java que puede extraer un archivo JAR y almacenar sus datos en el directorio (ubicación) especificado?

Si me quedo jar -xf filename.jar esto causa un error:

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

Respuesta

54

Adaptar este ejemplo: How to extract Java resources from JAR and zip archive

O probar este código:

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

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

+2

¿Esto no funciona para nadie más? Sigo lanzándome FileNotFoundExceptions por esto ..... – Flafla2

+0

Mismo problema para mí @ Flafla2. – MiJyn

+2

@lkjoel La razón por la que se lanza una excepción es porque esencialmente estás intentando escribir cosas como "dest/folder1/file1" antes de crear "dest/folder1". Para resolver esto, recomiendo iterar a través de la enumeración JarEntry de antemano, y convertirlo en una lista que está ordenada en getName(). Size() (de menor a mayor). De esta forma, creará todos los directorios necesarios antes de acceder a sus archivos/subdirectorios secundarios. – Destin

1

Su título no parece coincidir con la pregunta muy bien, pero si usted realmente quiere "escribir [a] programa Java extraer un archivo JAR "solo necesitas Class JarFile.

+0

sí quiero escribir un programa Java que extraerá un archivo jar –

4

JarFile clase.

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í quiero algo así, pero ¿cómo puedo guardar el archivo extraído en algún otro directorio. ¿Puedes por favor guiarme? –

5

Usted puede utilizar este fragmento de código como una referencia para obtener su tarea done.It es casi el mismo fragmento de código que se muestra arriba por @JuanZe, excepto que para los que fueron getti ng FileNotFoundException, he agregado un pequeño fragmento de código que verificará si el archivo existe y, si no lo tiene, creará la carpeta principal junto con los archivos y extraerá el contenido del archivo jar dentro de la carpeta de destino especificada.

Fragmento de código:

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

Este código recortado funcionará para aquellos que están recibiendo la Excepción de FileNotFound en el caso anterior – stacky

2

Esto es lo que yo haría para extraer toda mi carpeta de "recursos" de mi frasco. Es mucho más rápido usar BufferedReader y 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

Usando el lector de Buffered, se hace en segundos. Gran diferencia. Gracias –

1

Puede utilizar esta muy simple biblioteca para paquete de archivo/unpack frasco

JarManager

Muy simple

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

Puede también utilizar dependencia Maven

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

También necesita mi repositorio

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

Compruebe la última versión con el enlace de abajo para usar la última dependencia

favor utiliza mi public issue tracker si encuentra algunos errores

0

Bueno, aquí es mi versión, usando 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

Pregunta anterior.
Aquí es una respuesta actualizada usando:

  • Java 7 java.nio crear y copiar de manera eficiente entradas
  • Java 8 stream para ordenar y recoger las entradas lexicográfico (creado con el fin de siempre primero las carpetas).

Tenga en cuenta que he usado java.util.zip.ZipFile (la clase base) en lugar de java.util.jar.JarFile (la subclase).
El último realiza más cosas y no son necesarios para la extracción de archivos de un caso de uso de archivo.
Por lo tanto, reduce la sobrecarga y evita el aumento de excepciones relacionadas con problemas de seguridad.

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

    } 
} 
Cuestiones relacionadas