6 Stimmen

Überprüfen, ob ein Stream eine Zip-Datei ist

Wir haben Anforderungen, um festzustellen, ob ein eingehender InputStream auf eine ZIP-Datei oder ZIP-Daten verweist. Wir haben keinen Verweis auf die zugrunde liegende Quelle des Streams. Unser Ziel ist es, den Inhalt dieses Streams in einen OutputStream zu kopieren, der an einen anderen Ort gerichtet ist.

Ich habe versucht, den Stream mit ZipInputStream zu lesen und ein ZipEntry zu extrahieren. Das ZipEntry ist null, wenn der Stream eine reguläre Datei ist - wie erwartet -, jedoch verliere ich beim Überprüfen eines ZipEntry die ersten Bytes des Streams. Somit habe ich bereits am Anfang Daten aus dem Stream verloren, wenn ich merke, dass es sich um einen regulären Stream handelt.

Gedanken dazu, wie man überprüfen kann, ob der InputStream ein Archiv ist, ohne Daten zu verlieren, wären hilfreich.

Danke.

6voto

Galactus Punkte 766

Angenommen, Ihr ursprünglicher InputStream ist nicht gepuffert, würde ich versuchen, den ursprünglichen Stream in einen BufferedInputStream zu wickeln, bevor ich ihn in einen ZipInputStream wickele, um zu überprüfen. Sie können "mark" und "reset" im BufferedInputStream verwenden, um zur Anfangsposition im Stream zurückzukehren, nachdem Sie Ihre Überprüfung durchgeführt haben.

3voto

User0 Punkte 554

Das ist wie ich es gemacht habe.

Verwenden von mark/reset, um den Stream wiederherzustellen, wenn der GZIPInputStream ein falsches Zip-Format erkennt (wirft die ZipException).

/**
 * Wendet den Input-Stream mit GZIPInputStream an, wenn erforderlich.
 * @param inputStream
 * @return
 * @throws IOException
 */
private InputStream wrapIfZip(InputStream inputStream) throws IOException {
    if (!inputStream.markSupported()) {
        inputStream = new BufferedInputStream(inputStream);
    }
    inputStream.mark(1000);
    try {
        return new GZIPInputStream(inputStream);
    } catch (ZipException e) {
        inputStream.reset();
        return inputStream;
    }
}

2voto

Nickolay Olshevsky Punkte 12838

Sie können die ersten Bytes des Streams auf die ZIP-Lokalkopf-Signatur überprüfen (PK 0x03 0x04), das sollte für die meisten Fälle ausreichen. Wenn Sie mehr Präzision benötigen, sollten Sie die letzten ~100 Bytes nehmen und auf die Felder des zentralen Verzeichnislokators überprüfen.

1voto

Sie haben einen java.io.PushbackInputStream beschrieben - zusätzlich zu read() hat es ein unread(byte[]), das es Ihnen erlaubt, sie zurück an den Anfang des Streams zu schieben und sie erneut zu read().

Es ist in java.io seit JDK1.0 (obwohl ich zugebe, dass ich bis heute keine Verwendung dafür gesehen habe).

0voto

Kim Burgaard Punkte 3478

Es hört sich ein wenig wie ein Hack an, aber Sie könnten einen Proxy implementieren java.io.InputStream um zwischen ZipInputStream und dem Stream zu sitzen, den Sie ursprünglich an den Konstruktor von ZipInputStream übergeben haben. Ihr Proxy würde in einen Puffer streamen, bis Sie wissen, ob es sich um eine ZIP-Datei handelt oder nicht. Wenn nicht, dann rettet Sie der Puffer.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X