views:

327

answers:

3

I call a service which returns a gzipped file. I have the data as an InputStream (courtesy of javax.activation.DataHandler.getInputStream();) from the response.

What I would like to do is, without writing anything to disk, get an InputStream of the decompressed data in the file that is in the archive. The compressed file in this case is an xml document that I am trying to unmarshal using javax.xml.bind.Unmarshaller which takes an InputStream.

I'm currently trying to write the InputStream to an OutputStream (decompressing the data) and then I'll need to write it back to an InputStream. It's not working yet so I thought I would see if there was a better (I would hope so) approach.

I can write the initial InputStream to disk and get a gz file, and then read that file, get the compressed file out of it and go from there but I'd rather keep it all in memory is possible.

Update 1: Here is my current (not working - get a "Not in GZIP format" exception):

    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());

If instead of writing to a ByteArrayOutputStream I write to a FileOutputStream the first time around I get a compressed file (which I can manually open to get the xml file within) and the service (eBay) says it should be a gzip file so I'm not sure why I get a "Not in GZIP format" error.

Update 2: I tried something a little different - same error ("Not in GZIP format"). Wow, I just tried to end that parenthesis with a semi-colon. Anyways, here is my second attempt, which still does not work:

    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());
+2  A: 

Take a look at GZIPInputStream. Here's an example; the class handles this very transparently, it's almost no work to use.

Dean J
Just curiousity: why expliticily 1.4.2? Why not just the latest as available here? http://java.sun.com/javase/6/docs/api/java/util/zip/GZIPInputStream.html
BalusC
Sorry, I should have went with "I think first available in 1.4.2". Let me edit that one. :-)
Dean J
I am looking at GZIPInputStream in what I am currently working with although I get an "Not in GZIP format" exception. I don't understand this as I can write the file to disk and it IS a compressed file (gzip according to the documentation). I'll add what I currently (not working) have to the question.
Ryan Elkins
It may be a plain ZIP format instead of GZIP? Try ZIPInputStream as well, and report back?
Dean J
+1  A: 

Decorate the input stream with a GZIPInputStream.

InputStream decompressed = new GZIPInputStream(compressed);
erickson
+2  A: 

The following code should work. Keep in mind you'll have to handle exceptions properly.

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();
   }
}
Bryan Kyle