Question

Quel est le meilleur moyen de savoir si java.io.InputStream contient des données compressées?

Était-ce utile?

La solution

Les octets magiques du format ZIP sont 50 4B . Vous pouvez tester le flux (à l'aide de mark et réinitialiser - vous devrez peut-être tampon ), mais Je ne m'attendrais pas à ce que cette approche soit fiable à 100%. Il n’y aurait aucun moyen de le distinguer d’un fichier texte codé US-ASCII commençant par les lettres PK .

La meilleure meilleure méthode serait de fournir des métadonnées sur le format du contenu avant d'ouvrir le flux, puis de les traiter correctement.

Autres conseils

Introduction

Comme toutes les réponses ont 5 ans, je me sens obligé de noter ce qui se passe aujourd’hui. Je doute sérieusement qu'il faille lire les octets magiques du flux! C'est un code de bas niveau, il devrait être évité en général.

Réponse simple

miku écrit:

  

Si le flux peut être lu via ZipInputStream, il doit être compressé.

Oui, mais dans le cas de ZipInputStream , vous pouvez lire " signifie que le premier appel à .getNextEntry () renvoie une valeur non nulle. Aucune exception attraper et cetera. Donc, au lieu d’octets magiques, vous pouvez simplement:

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

Et c'est tout!

Réflexions générales sur la décompression

En général, il est apparu qu'il est beaucoup plus pratique de travailler avec des fichiers en mode [décompression] qu'avec des flux. Il existe plusieurs bibliothèques utiles, plus ZipFile a plus de fonctionnalités que ZipInputStream. Le traitement des fichiers zip est décrit ici: Qu'est-ce qu'un bon Bibliothèque Java pour compresser / décompresser des fichiers? Si vous pouvez travailler avec des fichiers, vous feriez mieux de le faire!

Exemple de code

Dans mon application, je n'avais besoin que de travailler avec des flux. Voilà donc la méthode que j'ai écrite pour décompresser:

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

Vous pouvez vérifier que les quatre premiers octets du flux sont la signature d'en-tête de fichier local qui démarre l'en-tête de fichier local qui traite chaque fichier dans un fichier ZIP, < un href = "http://www.pkware.com/documents/casestudies/APPNOTE.TXT" rel = "noreferrer"> comme indiqué dans la spécification ici : 50 4B 03 04 .

Un petit code de test montre que cela fonctionne:

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

m'a donné cette sortie:

50 4B 3 4 

Pas très élégant, mais fiable:

Si le flux peut être lu via ZipInputStream , il devrait être compressé.

Vérifier le numéro magique peut ne pas être la bonne option.

Les fichiers Docx ont également un nombre magique similaire 50 4B 3 4

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top