2010-01-14 15 views
23

Sto tentando di scrivere una funzione che accetterà uno InputStream con dati di file compressi e restituirà un altro InputStream con dati decompressi.Decompressione di un file da InputStream e restituzione di un altro InputStream

Il file zippato conterrà solo un singolo file e quindi non v'è alcun obbligo di directory che creano, ecc ...

Ho provato a guardare ZipInputStream e altri, ma sono confuso da tanti diversi tipi di flussi in Giava.

+1

Cosa avete già provato? Si prega di aggiungere qualche esempio di codice. –

risposta

40

Concetti

GZipinputstream è per i flussi (o file) ziped come gzip (estensione ".gz"). Non ha alcuna informazione di intestazione.

GZipInputStream is for [zippeddata] 

Se si dispone di un file zip vero e proprio, è necessario all'utente ZipFile di aprire il file, per chiedere l'elenco dei file (uno nel tuo esempio) e chiedere il flusso di input decompresso.

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

Il tuo metodo, se avete il file, sarebbe qualcosa di simile:

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

Leggendo un InputStream con il contenuto di un file .zip

Ok, se avete un InputStream che puoi usare (come dice @cletus) ZipInputStream. Legge uno stream che include i dati di intestazione.

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

Importante: se avete il file nel vostro PC è possibile utilizzare ZipFile classe per accedere a caso

Questo è un esempio di lettura di un file zip attraverso 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

Ho corretto il codice, ZipInputStream ha dovuto avvolgere il flusso di input originale :). Grazie! – helios

+0

Helios: zipinput.getNextEntry() restituirà un oggetto ZipEntry. Come posso convertirlo in un flusso? –

+0

zipinputstream rappresenta un inputstream dei dati decompressi del file. Ecco perché sto restituendo "zipinput". Ma deve iniziare a leggere le intestazioni e posizionarsi all'inizio degli attuali dati compressi. Ecco perché prima chiamo "getnextentry". Per fare in modo che zipinputstream legga quell'intestazione e si prepari a decomprimere la sua voce (e, naturalmente, a conoscere il nome file zippato :). – helios

2

A meno che non mi manchi qualcosa, dovresti assolutamente provare a far funzionare ZipInputStream e non c'è motivo di non farlo (l'ho sicuramente usato in diverse occasioni).

Quello che dovresti fare è provare a far funzionare ZipInputStream e se non puoi, inserisci il codice e ti aiuteremo a risolvere qualsiasi problema tu abbia.

Qualsiasi cosa tu faccia, non provare a reinventarne la funzionalità.

+2

sembra averlo provato e non ha capito come usarlo. – Bozho

+7

Per essere onesti, 'java.util.zip' è un'API piuttosto sgradevole – skaffman

6

Se è possibile modificare i dati di input, suggerirei di utilizzare GZIPInputStream.

GZipInputStream è diverso da ZipInputStream poiché si dispone di un solo dato al suo interno. Quindi l'intero flusso di input rappresenta l'intero file. In ZipInputStream l'intero stream contiene anche la struttura del file (s) al suo interno, che può essere molti.

+1

Il file non è nel mio controllo. È un file scaricato da un server. Ho usato per salvarlo su disco e quindi decomprimerlo, ma ora sto pensando di decomprimerlo in memoria. –

+0

Ciò che importa non è se i byte provengono da un socket di rete o da un file. La distinzione da fare è tra un archivio zip e un blob di dati compressi. Se hai scritto e letto i dati, forse non ti interesserebbe davvero l'archivio con i suoi metadati, e GZipStream sarebbe quello per cui andare. Stai ricevendo chiaramente un archivio (oppure salvandolo su un file e decomprimerlo probabilmente fallirebbe, almeno se decomprimerai eseguendo un programma di decompressione "standard"). Puoi infatti decomprimerlo in memoria usando ZipInputStream. –

2

E 'sulla sintassi Scala:

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