Распаковка файла из InputStream и возврат другого InputStream - PullRequest
26 голосов
/ 14 января 2010

Я пытаюсь написать функцию, которая будет принимать InputStream с данными в заархивированном файле и возвращать еще одну InputStream с разархивированными данными.

Заархивированный файл будет содержать только один файл, поэтому нет необходимости создавать каталоги и т. Д. *

Я пытался посмотреть на ZipInputStream и другие, но меня смущает очень много разных типов потоков в Java.

Ответы [ 4 ]

45 голосов
/ 14 января 2010

Concepts

GZipinputstream предназначен для потоков (или файлов), сжатых как gzip (расширение ".gz"). У него нет информации заголовка.

GZipInputStream is for [zippeddata]

Если у вас есть настоящий zip-файл, вы должны использовать ZipFile, чтобы открыть файл, запросить список файлов (один в вашем примере) и запросить распакованный поток ввода.

ZipFile is for a file with [header information + zippeddata]

Ваш метод, если у вас есть файл, будет выглядеть примерно так:

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

Чтение InputStream с содержимым ZIP-файла

Хорошо, если у вас есть InputStream, который вы можете использовать (как говорит @cletus) ZipInputStream. Он читает поток, включая данные заголовка.

ZipInputStream is for a stream with [header information + zippeddata]

Важно: если у вас есть файл на вашем компьютере, вы можете использовать ZipFile класс для случайного доступа к нему

Это пример чтения zip-файла через 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()
        }
    }
}
6 голосов
/ 14 января 2010

Если вы можете изменить входные данные, я бы предложил вам использовать GZIPInputStream.

GZipInputStream отличается от ZipInputStream, поскольку в нем есть только одна информация Таким образом, весь поток ввода представляет весь файл. В ZipInputStream весь поток содержит также структуру файла (файлов) внутри него, которая может быть много

4 голосов
/ 15 июля 2016

Используется синтаксис scala:

def unzipByteArray(input: Array[Byte]): String = {
    val zipInputStream = new ZipInputStream(new ByteArrayInputStream(input))
    val entry = zipInputStream.getNextEntry
    IOUtils.toString(zipInputStream, StandardCharsets.UTF_8)
}
2 голосов
/ 14 января 2010

Если я что-то упустил, вы должны обязательно попытаться заставить ZipInputStream работать, и нет никаких причин, по которым это не должно (я, конечно, использовал это несколько раз).

Что вам нужно сделать, это попытаться заставить ZipInputStream работать, и если вы не можете, опубликуйте код, и мы поможем вам с любыми проблемами.

Что бы вы ни делали, не пытайтесь заново изобрести его функциональность.

...