2011-01-11 15 views
5

Ho alcune domande generali sulla libreria java.util.zip. Quello che fondamentalmente facciamo è un'importazione e un'esportazione di molti piccoli componenti. In precedenza questi componenti sono stati importati ed esportati utilizzando un unico grande file, ad es .: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"/> 

Si prega di notare che l'ordine dei componenti durante l'importazione è rilevante.

Ora ogni componente dovrebbe occupare un proprio file che dovrebbe essere esternamente versione, QA-ed, bla, bla. Abbiamo deciso che l'output della nostra esportazione dovrebbe essere un file zip (con tutti questi file in) e l'input della nostra importazione dovrebbe essere un file zip simile. Non vogliamo far esplodere lo zip nel nostro sistema. Non vogliamo aprire flussi separati per ciascuno dei piccoli file. Le mie attuali domande:

Q1. Può il ZipInputStream garantire che le voci zip (i piccoli file) vengano lette nello stesso ordine in cui sono state inserite dalla nostra esportazione che utilizza ZipOutputStream? Presumo lettura è qualcosa di simile:


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

So che la directory centrale zip è messo alla fine del file zip, ma comunque le voci del file all'interno avere ordine sequenziale. So anche che fare affidamento sull'ordine è una brutta idea, ma voglio solo avere tutti i fatti in mente.

Q2. Se utilizzo ZipFile (che preferisco) qual è l'impatto sulle prestazioni della chiamata a getInputStream() centinaia di volte? Sarà molto più lento della soluzione ZipInputStream? Lo zip è aperto una sola volta e ZipFile è supportato da RandomAccessFile - è corretto? presumo la lettura è qualcosa di simile:


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. I flussi di input sono recuperati dallo stesso thread di sicurezza ZipFile (ad esempio, posso leggere voci diverse in thread diversi contemporaneamente)? Qualche penalità per le prestazioni?

Grazie per le vostre risposte!

risposta

3

Q1: sì, l'ordine sarà lo stesso in cui sono state aggiunte le voci.

Q2: si noti che a causa della struttura dei file di archivio zip e della compressione, nessuna delle soluzioni è esattamente in streaming; fanno tutti un certo livello di buffering. E se controlli i sorgenti JDK, le implementazioni condividono la maggior parte del codice. Non esiste un vero accesso casuale all'interno del contenuto, sebbene l'indice consenta di trovare blocchi che corrispondono a voci. Quindi penso che non ci dovrebbero essere differenze di prestazioni significative; soprattutto perché il SO farà comunque il caching dei blocchi del disco. Potresti voler semplicemente testare le prestazioni per verificarlo con un semplice caso di test.

Q3: Non conterei su questo; e molto probabilmente non lo sono. Se ritieni che un accesso concorrente possa essere d'aiuto (soprattutto perché la decompressione è legata alla CPU, quindi potrebbe essere d'aiuto), proverei a leggere l'intero file in memoria, a esporlo tramite ByteArrayInputStream e a costruire più lettori indipendenti.

+0

Hi StaxMan! Stavo controllando l'implementazione di ZipFile $ ZipFileInputStream in JDK6. Questo viene restituito da ZipFile.getInputStream. Ha la sincronizzazione anche se non so davvero quanto sia affidabile. –

+0

Sì, non posso dire per certo che sia privo di thread. Un'altra parte pericolosa è la sottostante libreria nativa di zlib, che sospetto non sia sicura per i thread. – StaxMan

+6

Posso testimoniare che non è infallibile, attraverso un'esperienza dolorosa. – Joel

0

Riguardo Q3, esperienza JENKINS-14362 suggerisce che zlib non è thread-safe anche operando sui flussi indipendenti, cioè che abbia qualche stato statico impropriamente condivisa. Non dimostrato, solo un avvertimento.

1

Ho rilevato che il solo elenco dei file con ZipInputStream è 8 volte più lento rispetto a 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); 

e

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

(Non li correre nella stessa classe. Fare due classi diverse e gestito separatamente)

+0

La mia impressione è che ZipFile stia leggendo l'indice zip mentre ZipInputStream sta "scorrendo" l'intero file zip leggendo un file dopo l'altro, FWIW. – rogerdpack

Problemi correlati