Come faccio ad avere l'InputStream dei dati decompressi da un InputStream dei dati compressi con gzip?

StackOverflow https://stackoverflow.com/questions/1744290

  •  20-09-2019
  •  | 
  •  

Domanda

io chiamo un servizio che restituisce un file zippato. Ho i dati come un InputStream (per gentile concessione di javax.activation.DataHandler.getInputStream();) dalla risposta.

Quello che vorrei fare è, senza scrivere nulla sul disco, ottenere un InputStream dei dati decompressi nel file che è in archivio. Il file compresso in questo caso è un documento XML che sto cercando di unmarshalling utilizzando javax.xml.bind.Unmarshaller che prende un InputStream.

Al momento sto cercando di scrivere l'InputStream ad un OutputStream (la decompressione dei dati) e poi ti bisogno di scrivere di nuovo a un InputStream. Non funziona eppure così ho pensato di vedere se c'era un (spero così) approccio migliore.

Posso scrivere l'InputStream iniziale per disco e ottenere un file gz, e quindi leggere il file, ottenere il file compresso fuori di esso e passare da lì, ma preferirei tenere tutto in memoria è possibile.

Aggiornamento 1: Qui è il mio attuale (che non funziona - ottenere un'eccezione "Not in formato gzip"):

    ByteArrayInputStream xmlInput = null;
    try {
        InputStream in = dh.getInputStream(); //dh is a javax.activation.DataHandler
        BufferedInputStream bis = new BufferedInputStream(in);
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        int bytes_read = 0;
        byte[] dataBuf = new byte[4096];
        while ((bytes_read = bis.read(dataBuf)) != -1) {
            bo.write(dataBuf, 0, bytes_read);
        }
        ByteArrayInputStream bin = new ByteArrayInputStream(bo.toByteArray());
        GZIPInputStream gzipInput = new GZIPInputStream(bin);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        dataBuf = new byte[4096];;
        bytes_read = 0;
        while ((bytes_read = gzipInput.read(dataBuf)) > 0) {
            out.write(dataBuf, 0, bytes_read);
        }
        xmlInput = new ByteArrayInputStream(out.toByteArray());

Se invece di scrivere a un ByteArrayOutputStream scrivo ad un FileOutputStream la prima volta intorno ho un file compresso (che posso aprire manualmente per ottenere il file XML all'interno) e il servizio (eBay) dice che dovrebbe essere un file gzip quindi non so perché ricevo un errore "Not in GZIP formato".

Aggiornamento 2: ho provato qualcosa di diverso - stesso errore ( "Non nel formato gzip"). Wow, ho solo cercato di porre fine a questa parentesi con un punto e virgola. In ogni modo, ecco il mio secondo tentativo, che ancora non funziona:

    ByteArrayInputStream xmlInput = null;
    try {
        GZIPInputStream gzipInput = new GZIPInputStream(dh.getInputStream());
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        int bytes_read = 0;
        byte[] dataBuf = new byte[4096];
        while ((bytes_read = gzipInput.read(dataBuf)) != -1) {
            bo.write(dataBuf, 0, bytes_read);
        }
        xmlInput = new ByteArrayInputStream(bo.toByteArray());
È stato utile?

Soluzione

Il seguente codice dovrebbe funzionare. Tenete a mente che dovrete gestire le eccezioni in modo corretto.

OutputStream out = null;
InputStream in = null;
try {
   out = /* some output stream */;
   in = new java.util.GZIPInputStream(/*some stream*/);
   byte[] buffer = new byte[4096];
   int c = 0;
   while (( c = in.read(buffer, 0, 4096)) > 0) {
      out.write(buffer, 0, c);
   }
} finally {
   if (in != null) {
      in.close();
   }
   if (out != null) {
      out.close();
   }
}

Altri suggerimenti

Decora il flusso di input con un GZIPInputStream .

InputStream decompressed = new GZIPInputStream(compressed);

Date un'occhiata a GZIPInputStream. Ecco un esempio ; la classe gestisce questo molto trasparente, è quasi nessun lavoro da utilizzare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top