web-dev-qa-db-fra.com

Décompresser un fichier d'InputStream et renvoyer un autre InputStream

J'essaie d'écrire une fonction qui acceptera un InputStream avec des données de fichier zippées et retournerait un autre InputStream avec des données décompressées.

Le fichier compressé ne contiendra qu'un seul fichier et il n'est donc pas nécessaire de créer des répertoires, etc ...

J'ai essayé de regarder ZipInputStream et d'autres mais je suis confus par tant de types de flux différents en Java.

30
Baishampayan Ghose

Concepts

GZipinputstream est destiné aux flux (ou fichiers) compressés au format gzip (extension ".gz"). Il ne contient aucune information d'en-tête.

GZipInputStream est pour [zippeddata]

Si vous avez un vrai fichier Zip, vous devez utiliser ZipFile pour ouvrir le fichier, demander la liste des fichiers (un dans votre exemple) et demander le flux d'entrée décompressé.

ZipFile est pour un fichier avec [informations d'en-tête + données zippées]

Votre méthode, si vous avez le fichier, serait quelque chose comme:

// ITS PSEUDOCODE!!

private InputStream extractOnlyFile(String path) {
   ZipFile zf = new ZipFile(path);
   Enumeration e = zf.entries();
   ZipEntry entry = (ZipEntry) e.nextElement(); // your only file
   return zf.getInputStream(entry);
}

Lecture d'un InputStream avec le contenu d'un fichier .Zip

Ok, si vous avez un InputStream, vous pouvez utiliser (comme le dit @cletus) ZipInputStream. Il lit un flux comprenant des données d'en-tête.

ZipInputStream est pour un flux avec [informations d'en-tête + données zippées]

Important: si vous avez le fichier sur votre PC, vous pouvez utiliser la classe ZipFile pour y accéder de manière aléatoire

Voici un exemple de lecture d'un fichier Zip via un InputStream:

import Java.io.FileInputStream;
import Java.util.Zip.ZipEntry;
import Java.util.Zip.ZipInputStream;


public class Main {
    public static void main(String[] args) throws Exception
    {
        FileInputStream fis = new FileInputStream("c:/inas400.Zip");

        // this is where you start, with an InputStream containing the bytes from the Zip file
        ZipInputStream zis = new ZipInputStream(fis);
        ZipEntry entry;
            // while there are entries I process them
        while ((entry = zis.getNextEntry()) != null)
        {
            System.out.println("entry: " + entry.getName() + ", " + entry.getSize());
                    // consume all the data from this entry
            while (zis.available() > 0)
                zis.read();
                    // I could close the entry, but getNextEntry does it automatically
                    // zis.closeEntry()
        }
    }
}
45
helios

Si vous pouvez modifier les données d'entrée, je vous suggère d'utiliser GZIPInputStream.

GZipInputStream est différent de ZipInputStream car vous n'avez qu'une seule donnée à l'intérieur. Ainsi, l'ensemble du flux d'entrée représente l'ensemble du fichier. Dans ZipInputStream, le flux entier contient également la structure du ou des fichiers à l'intérieur, qui peut être multiple.

6
nanda

C'est sur scala syntaxe:

def unzipByteArray(input: Array[Byte]): String = {
    val zipInputStream = new ZipInputStream(new ByteArrayInputStream(input))
    val entry = zipInputStream.getNextEntry
    IOUtils.toString(zipInputStream, StandardCharsets.UTF_8)
}
4
Roman Kazanovskyi

À moins que quelque chose me manque, vous devez absolument essayer de faire fonctionner ZipInputStream et il n'y a aucune raison que cela ne le soit pas (je l'ai certainement utilisé à plusieurs reprises).

Ce que vous devez faire est d'essayer de faire fonctionner ZipInputStream et si vous ne le pouvez pas, postez le code et nous vous aiderons avec les problèmes que vous rencontrez.

Quoi que vous fassiez, n'essayez pas de réinventer ses fonctionnalités.

2
cletus