Domanda

Qual è il modo migliore per scoprire i java.io.InputStream contiene dati compressi?

È stato utile?

Soluzione

I byte magici per il formato ZIP sono 50 4B . È possibile testare lo stream (utilizzando mark e reset - potrebbe essere necessario buffer ) ma Non mi aspetto che questo sia un approccio affidabile al 100%. Non ci sarebbe modo di distinguerlo da un file di testo con codifica US-ASCII che è iniziato con le lettere PK .

Il migliore sarebbe fornire metadati sul formato del contenuto prima di aprire lo stream e quindi trattarlo in modo appropriato.

Altri suggerimenti

Introduzione

Dato che tutte le risposte hanno 5 anni, ho il dovere di scrivere, cosa sta succedendo oggi. Dubito seriamente che si dovrebbero leggere i byte magici del flusso! È un codice di basso livello, dovrebbe essere evitato in generale.

Risposta semplice

miku scrive:

  

Se lo Stream può essere letto tramite ZipInputStream, dovrebbe essere compresso.

Sì, ma in caso di ZipInputStream " può essere letto " significa che la prima chiamata a .getNextEntry () restituisce un valore non nullo. Nessuna eccezione, ecc. Quindi, invece di analizzare i byte magici, puoi semplicemente fare:

boolean isZipped = new ZipInputStream(yourInputStream).getNextEntry() != null;

E questo è tutto!

Pensieri di decompressione generali

In generale, è sembrato che sia molto più comodo lavorare con i file mentre si [zippano], piuttosto che con i flussi. Esistono diverse utili librerie, inoltre ZipFile ha più funzionalità di ZipInputStream. La gestione dei file zip è discussa qui: Che cos'è un bene Libreria Java per comprimere / decomprimere i file? Quindi se riesci a lavorare con i file è meglio che tu faccia!

Esempio di codice

Nella mia applicazione avevo bisogno di lavorare solo con stream. Questo è il metodo che ho scritto per decomprimere:

import org.apache.commons.io.IOUtils;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public boolean unzip(InputStream inputStream, File outputFolder) throws IOException {

    ZipInputStream zis = new ZipInputStream(inputStream);

    ZipEntry entry;
    boolean isEmpty = true;
    while ((entry = zis.getNextEntry()) != null) {
        isEmpty = false;
        File newFile = new File(outputFolder, entry.getName());
        if (newFile.getParentFile().mkdirs() && !entry.isDirectory()) {
            FileOutputStream fos = new FileOutputStream(newFile);
            IOUtils.copy(zis, fos);
            IOUtils.closeQuietly(fos);
        }
    }

    IOUtils.closeQuietly(zis);
    return !isEmpty;
}

È possibile verificare che i primi quattro byte dello stream siano la firma dell'intestazione del file locale che avvia la intestazione del file locale che procede ogni file in un file ZIP, < a href = "http://www.pkware.com/documents/casestudies/APPNOTE.TXT" rel = "noreferrer"> come mostrato nelle specifiche qui essere 50 4B 03 04 .

Un piccolo codice di prova mostra che funziona:

byte[] buffer = new byte[4];

try {
    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("so.zip"));
    ZipEntry ze = new ZipEntry("HelloWorld.txt");
    zos.putNextEntry(ze);
    zos.write("Hello world".getBytes());
    zos.close();

    FileInputStream is = new FileInputStream("so.zip");
    is.read(buffer);
    is.close();
}
catch(IOException e) {
    e.printStackTrace();
}

for (byte b : buffer) { 
    System.out.printf("%H ",b);
}

Mi ha dato questo output:

50 4B 3 4 

Non molto elegante, ma affidabile:

Se lo Stream può essere letto tramite ZipInputStream , dovrebbe essere compresso.

Controllare il numero magico potrebbe non essere l'opzione giusta.

Anche i file Docx hanno un simile numero magico 50 4B 3 4

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top