2010-01-14 15 views
23

Estoy intentando escribir una función que aceptará un InputStream con datos de archivo comprimido y devolvería otro InputStream con datos descomprimidos.Descomprimir un archivo de InputStream y devolver otro InputStream

El archivo comprimido contiene sólo un único archivo y por lo tanto no hay ningún requisito de creación de directorios, etc ...

He intentado mirar ZipInputStream y otros, pero estoy confundido por tantos tipos diferentes de flujos de Java.

+1

¿Qué ya se trate? Por favor agrega un ejemplo de código. –

Respuesta

40

Conceptos

GZIPInputStream es para los flujos (o archivos) ziped como gzip (".gz" extensión). No tiene ninguna información de encabezado.

GZipInputStream is for [zippeddata] 

Si usted tiene un archivo zip real, usted tiene que ZipFile usuario a abrir el archivo, pedir la lista de archivos (uno en su ejemplo) y pregunte por el flujo de entrada descomprimido.

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

Su método, si tiene el archivo, sería algo así como:

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

Lectura de un InputStream con el contenido de un archivo .zip

Ok, si usted tiene un InputStream que puede usar (como @cletus dice) ZipInputStream. Lee una secuencia que incluye datos de encabezado.

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

Importante: si tiene el archivo en su PC puede utilizar ZipFile clase para acceder a ella de forma aleatoria

Ésta es una muestra de la lectura de un archivo zip a través de 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() 
     } 
    } 
} 
+0

Corregí el código, ZipInputStream tenía que envolver el flujo de entrada original :). Gracias! – helios

+0

Helios: zipinput.getNextEntry() devolverá un objeto ZipEntry. ¿Cómo lo convierto en una secuencia? –

+0

zipinputstream representa un flujo de entrada de los datos descomprimidos del archivo. Es por eso que estoy devolviendo "zipinput". Pero tiene que leer los encabezados y la posición al comienzo de los datos comprimidos actuales para comenzar. Es por eso que primero llamo "getnextentry". Para hacer que zipinputstream lea ese encabezado y prepararse para descomprimir su entrada (y, por supuesto, para saber el nombre de archivo comprimido :). – helios

2

A menos que me falta algo, deberías tratar de hacer que ZipInputStream funcione y no hay ninguna razón para que no ocurra (ciertamente lo he usado en varias ocasiones).

Lo que debes hacer es intentar que ZipInputStream funcione y si no puedes, publica el código y te ayudaremos con cualquier problema que tengas.

Haga lo que haga, no intente ni reinvente su funcionalidad.

+2

Parece que lo intentó y no supo cómo usarlo. – Bozho

+7

Para ser justos, 'java.util.zip' es una API bastante desagradable – skaffman

6

Si puede cambiar los datos de entrada, le sugiero que use GZIPInputStream.

GZipInputStream es diferente de ZipInputStream ya que solo tiene un dato dentro. Entonces toda la secuencia de entrada representa el archivo completo. En ZipInputStream toda la secuencia contiene también la estructura de los archivos dentro de ella, que pueden ser muchos.

+1

El archivo no está bajo mi control. Es un archivo que descargo de un servidor. Solía ​​guardarlo en el disco y luego descomprimirlo, pero ahora estoy pensando en descomprimirlo en la memoria. –

+0

Lo que realmente importa no es si los bytes se originan desde un socket de red o desde un archivo. La distinción que se debe hacer es entre un archivo zip y un blob de datos comprimidos. Si escribió y leyó los datos, tal vez no le interesaría realmente el archivo con sus metadatos, y entonces GZipStream sería el indicado. Está claro que está recibiendo un archivo (o bien guardándolo en un archivo y descomprimirlo probablemente fallaría, al menos si descomprimiera ejecutando un programa de descompresión "estándar"). De hecho, puede descomprimirlo en la memoria, utilizando ZipInputStream. –

2

Es sobre la sintaxis Scala:

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