2011-03-30 12 views
12

Probé el paquete java.util.zip, es demasiado lento.¿Cuál es la forma más rápida de extraer 1 archivo de un archivo zip que contiene una gran cantidad de archivos?

Luego encontré LZMA SDK y 7z jbinding pero también les falta algo. El LZMA SDK no proporciona un tipo de documentación/tutorial de cómo usarlo, es muy frustrante. No javadoc

Mientras que 7z jbinding no proporciona una manera simple de extraer solo 1 archivo, sin embargo, solo proporciona la forma de extraer todo el contenido del archivo zip. Además, no proporciona una forma de especificar una ubicación para colocar el archivo descomprimido.

¿Alguna idea por favor ???

Respuesta

15

¿Cómo es tu código con java.util.zip y qué tan grande de un archivo zip estás tratando?

soy capaz de extraer una entrada de 4 MB de un archivo de 200 MB zip con 1.800 entradas en menos de un segundo con esto:

OutputStream out = new FileOutputStream("your.file"); 
FileInputStream fin = new FileInputStream("your.zip"); 
BufferedInputStream bin = new BufferedInputStream(fin); 
ZipInputStream zin = new ZipInputStream(bin); 
ZipEntry ze = null; 
while ((ze = zin.getNextEntry()) != null) { 
    if (ze.getName().equals("your.file")) { 
     byte[] buffer = new byte[8192]; 
     int len; 
     while ((len = zin.read(buffer)) != -1) { 
      out.write(buffer, 0, len); 
     } 
     out.close(); 
     break; 
    } 
} 
+1

Estamos haciendo una aplicación web para el uso de fuera ..... somos hablando de 20 solicitudes por segundo. Hemos examinado que la velocidad de descomprimir un archivo usando java.util.zip sería entre 0.5s a 2s. Eso es lento – lamwaiman1988

+2

Supongo que estás hablando de 20 solicitudes por segundo que necesitan un solo archivo de un zip. ¿Por qué no simplemente descomprimirlos completamente antes de tiempo y servirlos directamente desde el sistema de archivos? – WhiteFang34

+4

su código sería aún más rápido si tuviera un BufferedInputStream entre FileInputStream y ZipInputStream. – EJP

6

Utilice un ZipFile en lugar de un ZipInputStream.

Aunque la documentación no lo indica (está en los documentos para JarFile), debe usar operaciones de archivos de acceso aleatorio para leer el archivo. Dado que un archivo ZIP contiene un directorio en una ubicación conocida, esto significa que debe pasar mucho menos IO para encontrar un archivo en particular.

Algunas advertencias: a mi leal saber y entender, la implementación de Sun usa un archivo mapeado en memoria. Esto significa que su espacio de direcciones virtuales debe ser lo suficientemente grande como para contener el archivo y todo lo demás en su JVM. Que puede ser un problema para un servidor de 32 bits. Por otro lado, puede ser lo suficientemente inteligente como para evitar la asignación de memoria en 32 bits, o el mapa de memoria solo el directorio; No lo he intentado.

Además, si usa varios archivos, asegúrese de usar un try/finally para asegurarse de que el archivo esté cerrado después de su uso.

7

No he comparado la velocidad pero con java 7 o superior, extraigo un archivo de la siguiente manera.
Me imagino que es más rápido que el ZipFile API:

Un breve ejemplo la extracción de META-INF/MANIFEST.MF de un archivo zip test.zip:

// file to extract from zip file 
String file = "MANIFEST.MF"; 
// location to extract the file to 
File outputLocation = new File("D:/temp/", file); 
// path to the zip file 
Path zipFile = Paths.get("D:/temp/test.zip"); 

// load zip file as filesystem 
try (FileSystem fileSystem = FileSystems.newFileSystem(zipFile, null)) { 
    // copy file from zip file to output location 
    Path source = fileSystem.getPath("META-INF/" + file); 
    Files.copy(source, outputLocation.toPath()); 
} 
+0

gracias. Esto funciona :) –

+0

Funciona, y muy rápido ... esta debería ser la respuesta aceptada (suponiendo Java 7 o superior). – leo

Cuestiones relacionadas