如何从GZIP数据的InputStream中获取解压后数据的InputStream?

9
我调用了一个返回gzipped文件的服务。我有响应的InputStream(由javax.activation.DataHandler.getInputStream();提供)中的数据。我想做的是,在不将任何内容写入磁盘的情况下,获取归档文件中已解压缩数据的InputStream。在这种情况下,压缩文件是我正在尝试使用javax.xml.bind.Unmarshaller进行取消编组的xml文档,它需要一个InputStream。
目前,我正在尝试将InputStream写入OutputStream(解压缩数据),然后我需要将其写回到InputStream。它还没有起作用,所以我想看看是否有更好的方法(我希望如此)。
如果可能,我可以将初始InputStream写入磁盘并获取gz文件,然后读取该文件,从中获取压缩文件并从那里继续,但我宁愿将所有内容保存在内存中。
更新1:这是我的当前代码(未能运行-会出现“不在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());

如果我不使用ByteArrayOutputStream,而是第一次写入FileOutputStream,那么我会得到一个压缩文件(我可以手动打开其中的xml文件),而且服务(eBay)说应该是gzip文件,所以我不确定为什么会出现“非GZIP格式”的错误。
更新2:我尝试了一些不同的东西 - 仍然出现相同的错误(“非GZIP格式”)。哇,我刚刚试图用分号结束括号。无论如何,这是我的第二次尝试,仍然不起作用。
    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());

看起来一个大问题是eBay说他们给了我一个gzip,但实际上是一个zip。 - Ryan Elkins
3个回答

5

使用GZIPInputStream装饰输入流。

InputStream decompressed = new GZIPInputStream(compressed);

2
以下代码应该可以运行。请记住,您需要正确处理异常。
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();
   }
}

0

看一下GZIPInputStream。这里有一个例子;这个类处理得非常透明,使用起来几乎不需要任何工作。


1
只是好奇:为什么明确使用1.4.2版本?而不是只使用此处提供的最新版本?http://java.sun.com/javase/6/docs/api/java/util/zip/GZIPInputStream.html - BalusC
抱歉,我应该说“我认为首次出现在1.4.2版本”。让我编辑一下。 :-) - Dean J
我正在研究GZIPInputStream,但是我遇到了“不在GZIP格式中”的异常。我不理解这个异常,因为我可以将文件写入磁盘并且它确实是一个压缩文件(根据文档是gzip格式)。我会将我目前的代码(不起作用的)添加到问题中。 - Ryan Elkins
可能是普通的ZIP格式而不是GZIP?也尝试使用ZIPInputStream,并回报结果? - Dean J

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接