2011-01-11 11 views
5

Tengo algunas preguntas generales con respecto a la biblioteca java.util.zip. Lo que básicamente hacemos es importar y exportar muchos componentes pequeños. Anteriormente estos componentes fueron importados y exportados utilizando un único archivo grande, por ejemplo .:java.util.zip - ZipInputStream v.s. ZipFile

<component-type-a id="1"/> 
<component-type-a id="2"/> 
<component-type-a id="N"/> 

<component-type-b id="1"/> 
<component-type-b id="2"/> 
<component-type-b id="N"/> 

Tenga en cuenta que el orden de los componentes durante la importación es relevante.

Ahora cada componente debe ocupar su propio archivo que debe ser externamente versionado, QA-ed, bla, bla. Decidimos que el resultado de nuestra exportación debería ser un archivo zip (con todos estos archivos) y la entrada de nuestra importación debería ser un archivo zip similar. No queremos explotar el zip en nuestro sistema. No queremos abrir flujos separados para cada uno de los archivos pequeños. Mis preguntas actuales:

Q1. ¿Puede el ZipInputStream garantizar que las entradas zip (los pequeños archivos) se leerán en el mismo orden en que fueron insertadas por nuestra exportación que usa ZipOutputStream? Asumo la lectura es algo así como:


ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis)); 
ZipEntry entry; 
while((entry = zis.getNextEntry()) != null) 
{ 
     //read from zis until available 
} 

Sé que el directorio central de cremallera se puso al final del archivo zip, pero sin embargo las entradas del archivo de Inside orden secuencial. También sé que confiar en la orden es una idea desagradable, pero solo quiero tener todos los hechos en mente.

Q2. Si utilizo ZipFile (que prefiero) ¿cuál es el impacto en el rendimiento de llamar al getInputStream() cientos de veces? ¿Será mucho más lento que la solución ZipInputStream? El zip se abre solo una vez y ZipFile está respaldado por RandomAccessFile - ¿es correcto? Asumo la lectura es algo así como:


ZipFile zipfile = new ZipFile(argv[0]); 
Enumeration e = zipfile.entries();//TODO: assure the order of the entries 
while(e.hasMoreElements()) { 
     entry = (ZipEntry) e.nextElement(); 
     is = zipfile.getInputStream(entry)); 
} 

Q3. ¿Se recuperan las secuencias de entrada del mismo subproceso ZipFile? (Por ejemplo, ¿puedo leer diferentes entradas en diferentes subprocesos simultáneamente)? ¿Alguna penalización de rendimiento?

Gracias por sus respuestas!

Respuesta

3

Q1: sí, el orden será el mismo en que se agregaron las entradas.

Q2: tenga en cuenta que debido a la estructura de los archivos comprimidos zip y la compresión, ninguna de las soluciones está transmitiendo exactamente; todos hacen algún nivel de almacenamiento en búfer. Y si consulta las fuentes JDK, las implementaciones comparten la mayoría del código. No hay acceso aleatorio real dentro del contenido, aunque el índice permite encontrar fragmentos que corresponden a las entradas. Entonces, creo que no debería haber diferencias significativas de rendimiento; especialmente porque OS hará caché de bloques de disco de todos modos. Es posible que desee probar el rendimiento para verificar esto con un caso de prueba simple.

Q3: No contaría con esto; y lo más probable es que no lo sean. Si realmente crees que el acceso simultáneo sería útil (sobre todo porque la descompresión está unida a la CPU, por lo que podría ser útil), trataría de leer todo el archivo en la memoria, exponer a través de ByteArrayInputStream y construir múltiples lectores independientes.

+0

Hola StaxMan! Estaba comprobando la implementación de ZipFile $ ZipFileInputStream en JDK6. Esto es devuelto por ZipFile.getInputStream Aunque tiene sincronización, realmente no sé qué tan confiable es eso. –

+0

Sí, no puedo decir con seguridad que no sea seguro para subprocesos. Una parte más peligrosa es la biblioteca zlib nativa subyacente, que sospecho que no es segura para subprocesos. – StaxMan

+6

Puedo testificar el hecho de que no es peligroso para los hilos, a través de una experiencia dolorosa. – Joel

0

En cuanto a la Q3, experiencia en JENKINS-14362 sugiere que zlib no es seguro para subprocesos incluso cuando se opera en corrientes no relacionadas, es decir que tiene algún estado estático incorrectamente compartido. No probado, solo una advertencia.

1

He medido que el solo hecho de listar los archivos con ZipInputStream es 8 veces más lento que con ZipFile.

long t = System.nanoTime(); 
    ZipFile zip = new ZipFile(jarFile); 
    Enumeration<? extends ZipEntry> entries = zip.entries(); 
    while (entries.hasMoreElements()) 
    { 
     ZipEntry entry = entries.nextElement(); 

     String filename = entry.getName(); 
     if (!filename.startsWith(JAR_TEXTURE_PATH)) 
      continue; 

     textureFiles.add(filename); 
    } 
    zip.close(); 
    System.out.println((System.nanoTime() - t)/1e9); 

y

long t = System.nanoTime(); 
    ZipInputStream zip = new ZipInputStream(new FileInputStream(jarFile)); 
    ZipEntry entry; 
    while ((entry = zip.getNextEntry()) != null) 
    { 
     String filename = entry.getName(); 
     if (!filename.startsWith(JAR_TEXTURE_PATH)) 
      continue; 

     textureFiles.add(filename); 
    } 
    zip.close(); 
    System.out.println((System.nanoTime() - t)/1e9); 

(No ejecutarlos en la misma clase. Hacer dos clases diferentes y ejecutar por separado)

+0

Mi corazonada es que ZipFile está leyendo el índice zip mientras que ZipInputStream está "recorriendo" todo el archivo zip leyendo un archivo tras otro, FWIW. – rogerdpack

Cuestiones relacionadas