简体   繁体   English

我如何gzip一个InputStream并返回一个InputStream?

[英]How can I gzip an InputStream and return an InputStream?

I am starting with a response from a HTTP request: 我从HTTP请求的响应开始:

InputStream responseInputStream = response.getEntityInputStream()

I need to gzip that response so I can upload it to s3 and save it compressed: 我需要对该响应进行gzip压缩,以便将其上传到s3并将其压缩保存:

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

I am aware that I can get the byte[] array out of responseInputStream and then gzip them into a new InputStream . 我知道我可以从responseInputStream获取byte[]数组,然后将其gzip压缩到新的InputStream However, that can be very inefficient with a large amount of data. 但是,如果处理大量数据,效率可能非常低。

I know that there have been similar questions asked on SO, but I have not found anything that seems to address the specific need of starting with an InputStream and finishing with a gzipped InputStream . 我知道在SO上也有类似的问题,但是我还没有发现任何东西可以解决从InputStream开始并以gzip压缩的InputStream完成的特定需求。

Thanks for any help! 谢谢你的帮助!

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

}

You are right, my previous example was wrong. 您是对的,我之前的示例是错误的。 You can use piped streams. 您可以使用管道流。 The catch here is that you cannot use the input and output stream from the same thread. 这里的问题是您不能使用来自同一线程的输入和输出流。 Also don't forget to join() on the writing thread. 同样不要忘记在编写线程上join() You can test my example by supplyng two parameters: 您可以通过提供两个参数来测试我的示例:

  • args[0] -> the source file args [0]->源文件
  • args[1] -> the destination to write the compressed content args [1]->写入压缩内容的目标

PS: @11thdimension was a few minutes faster with his piped stream solutions, so if you find this helpful please accept his answer PS:@ 11thdimension使用他的管道流解决方案要快几分钟,因此,如果您觉得这有帮助,请接受他的回答

I think you're looking for a PipedInputStream 我认为您正在寻找PipedInputStream

Here's how it can be done. 这是可以完成的。

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

I haven't tested this code, please let me know if this works. 我尚未测试此代码,请告诉我是否可行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM