2010-11-12 9 views
6

Ich bin fest mit diesem JUnit-Test:Warum kann ZipInputStream die Ausgabe von ZipOutputStream nicht lesen?

public void test() throws Exception { 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    ZipOutputStream zipOut = new ZipOutputStream(out); 
    zipOut.putNextEntry(new ZipEntry("file")); 
    zipOut.write((new byte[] { 0x01, 0x02, 0x03 })); 
    zipOut.closeEntry(); 
    zipOut.close(); 

    ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(out.toByteArray())); 
    ZipEntry entry = zipIn.getNextEntry(); 
    assertNotNull(entry); 
    assertEquals("file", entry.getName()); 
    assertEquals(3, entry.getSize()); 
} 

ich eine Datei mit dem Namen „Datei“ und ein Gehalt von drei Bytes zu einem ZipOutputStream zu schreiben. Dann versuche ich, die erstellten Daten mit einem ZipInputStream zu lesen, aber die letzte Assert schlägt fehl, weil entry.getSize()-1 und nicht 3 ist, wie erwartet.

Was mache ich hier falsch? Was muss ich ändern, um den Inhalt von "Datei" wiederherzustellen? Ich denke, ich muss zuerst die Länge kennen, um die Daten aus dem Stream lesen zu können?

+0

Ihr Code versucht - in der Tat es nicht funktioniert. Ich bin verwirrt. Untersuchung .. –

+0

Got it. Antwort unten. –

Antwort

4

Sie haben tatsächlich den Inhalt des Eintrags zu lesen, dann entry.getSize() wird die richtige Größe zurück .

byte[] buf = new byte[1024]; 
    int len; 
    while ((len = zipIn.read(buf)) > 0) { 
     // use data; 
    } 
+0

Oh, das ist nett. Ich habe es versäumt, nach dem Lesen der Daten in die Infofelder des zipEntry zu schauen ... Danke für diesen Hinweis! – tangens

+2

Die Sache ist, es gibt einen LOC-Eintrag vor einem ZipEntry und einen EXT-Eintrag nach einem ZipEntry. Beide haben ein Größenfeld. ZipOutputStream schreibt immer 0 in LOC.size, während andere Archiver die Größe sowohl in LOC als auch in EXT schreiben. Ich frage mich, wie viele Probleme dies verursachen kann, und wie ZipOutputStream schreiben Sie die Größe in der LOC? – rustyx

1

Ich fand die Antwort von mir: entry enthält nicht die richtige Größe, aber mit jedem zipIn.getNextEntry() erhalten Sie einen neuen Stream, um den Inhalt Ihres Eintrags aus zu lesen. Lies einfach den Stream bis zum Ende und du hast die Daten deiner Eingabe.

In meinem JUnit-Test die letzte Zeile wie folgt aussehen könnte:

byte[] restoredContent = new byte[ 10 ]; 
assertEquals(3, zipIn.read(restoredContent)); 

Jetzt funktioniert alles einwandfrei.

1

API doc für ZipEntry lesen. Es heißt "wenn bekannt". Sie können den Inhalt lesen mit der folgenden (es druckt nur die Größe des ZipEntry, es Daten verarbeitet entsprechend ändern):

ZipEntry entry = zipIn.getNextEntry(); 
int BUFSIZE = 1024; 
byte [] buffer = new byte[BUFSIZE]; 
int read = 0; 
int total = 0; 
while((read = zipIn.read(buffer, 0, BUFSIZE)) >0) { 
    total += read; 
    // what do you want to do with the data read? Do it here 
} 
System.err.println("Total: " + total); 
-1

Das gleiche Problem hier:

Zur Einstiegslesen!

ZipInputStream kann die Ausgabe von ZipOutputStream nicht lesen;

neue ZipFile (Datei) nicht mit einem Fehler

keine mögliche Erklärung!

Archiv-Viewer-Programm öffnet die Zip-Datei in Ordnung!

LÖSUNG: Äh ... es war schließlich keine Zip-Datei ... es war ein tar namens 'folder.zip'. Archiv-Viewer war schlau genug ...

Zu denen mit diesem Problem: Doppel-Check !!!

+2

Es tut mir leid, aber wovon redest du? Du hast eine TAR mit einem ZipOutputStream geschrieben ?? – rustyx

0

Vor kurzem hatte ich ein ähnliches Problem beim Lesen einer Zip-Bytes mit ZipOutputStream erstellt.

Das folgende Snippet führte zu java.lang.NegativeArraySizeException.

zipEntry = zipInputStream.getNextEntry(); 
byte[] bytes = new byte[(int) zipEntry.getSize()]; 

Eine schnelle Lösung es die alle Bytes des aktuellen Eintrags zu lesen war zu Apache commons-io IOUtils zu verwenden.

zipEntry = zipInputStream.getNextEntry(); 
byte[] bytes = org.apache.commons.io.IOUtils.toByteArray(zipInputStream); 

Ich hoffe, dass dies für jemanden hilfreich sein wird.

Verwandte Themen