1

我开始从一个HTTP请求的响应:如何gzip InputStream并返回InputStream?

InputStream responseInputStream = response.getEntityInputStream() 

我需要给gzip这种反应,所以我可以把它上传到S3并保存压缩:

this.s3.putObject(new PutObjectRequest(bucketName, key, gzippedResponseInputStream, meta)); 

我知道我可以从responseInputStream中获得byte[]阵列,然后将它们gzip压入新的InputStream。但是,对于大量的数据来说,这可能效率很低。

我知道在SO上也有类似的问题,但我还没有找到任何似乎解决以InputStream开头并以gzipped InputStream结束的特定需求的任何内容。

感谢您的帮助!

+1

您是否检查过此答案? http://stackoverflow.com/a/19326492/2588800 –

+0

哇,谢谢@SvetlinZarev - 工作!我一直在寻找通过尝试所有我找到的“解决方案”,而迄今为止这些解决方案都没有奏效,但你的建议做到了!谢谢! – chaimp

回答

3
public final class Example { 
    public static void main(String[] args) throws IOException, InterruptedException { 
     final PipedInputStream inputStream = new PipedInputStream(); 
     final PipedOutputStream outputStream = new PipedOutputStream(inputStream); 

     Thread compressorThread = new Thread() { 
      @Override 
      public void run() { 
       try (FileInputStream dataSource = new FileInputStream(args[0])) { 
        try (GZIPOutputStream sink = new GZIPOutputStream(outputStream)) { 
         final byte[] buffer = new byte[8 * 1024]; 
         for (int bytesRead = dataSource.read(buffer); bytesRead >= 0; bytesRead = dataSource.read(buffer)) { 
          sink.write(buffer, 0, bytesRead); 
         } 
        } 
       } catch (IOException ex) { 
        //TODO handle exception -> maybe use callable + executor 
       } 
      } 
     }; 
     compressorThread.start(); 

     try (FileOutputStream destination = new FileOutputStream(args[1])) { 
      final byte[] buffer = new byte[8 * 1024]; 
      for (int bytesRead = inputStream.read(buffer); bytesRead >= 0; bytesRead = inputStream.read(buffer)) { 
       destination.write(buffer, 0, bytesRead); 
      } 
     } 

     compressorThread.join(); 
    } 

} 

你说得对,我以前的例子是错的。您可以使用管道流。这里的问题是你不能使用来自同一线程的输入和输出流。在编写线程上也不要忘记join()。可以通过supplyng两个参数测试我例如:

  • ARGS [0] - >源文件
  • ARGS [1] - >目的地写压缩内容

PS:@ 11thdimension是几分钟与他的管道流的解决方案更快,所以如果你有所帮助,请接受他的回答

+0

GZIPInputStream用于取得已压缩的数据并对其进行解压缩。 我在实现之前就已经尝试过了。但是,它在文档中也说得很清楚。 感谢您的快速响应,但这是不正确的。 – chaimp

+0

谢谢@svetlin我用你在问题的评论中找到的解决方案结束了工作,但我很欣赏这一点,并且我相信它是有效的,所以我会将其标记为“已接受”。 – chaimp

3

我认为你正在寻找一个PipedInputStream

这是如何做到的。

public InputStrema getGZipStream() { 
    final PipedOutputStream pos = new PipedOutputStream(); 
    PipedInputStream pis = new PipedInputStream(); 

    try (final InputStream responseInputStream = response.getEntityInputStream(); 
    ){ 
     pis.connect(pos); 

     Thread thread = new Thread() { 
      public void run() { 
       startWriting(pos, responseInputStream); 
      } 
     }; 
     thread.start(); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 

    return pis; 
} 

public void startWriting(OutputStream out, InputStream in) { 
    try (GZIPOutputStream gOut = GZIPOutputStream(out);) { 
     byte[] buffer = new byte[10240]; 
     int len = -1; 
     while ((len = in.read(buffer)) != -1) { 
      gOut.write(buffer, 0, len); 
     } 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } finally { 
     try { 
      out.close(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

我还没有测试过这个代码,请让我知道,如果这个工程。

+1

它赢了;因为当你退出'try'主体时你会关闭'pis' - 所以你会返回一个封闭的流; –

+0

我在想同样的事情。安全是否尝试在方法结束时关闭流?无论如何,我会修改代码来处理它。 – 11thdimension

+0

改变了,至少现在不应该有封闭流问题。 – 11thdimension