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

Java 我如何gzip一个InputStream并返回一个InputStream?,java,inputstream,outputstream,gzipinputstream,gzipoutputstream,Java,Inputstream,Outputstream,Gzipinputstream,Gzipoutputstream,我从HTTP请求的响应开始: InputStream responseInputStream = response.getEntityInputStream() 我需要gzip该响应,以便将其上载到s3并将其压缩保存: this.s3.putObject(new PutObjectRequest(bucketName, key, gzippedResponseInputStream, meta)); 我知道我可以将byte[]数组从responseInputStream中取出,然后将它们gz

我从HTTP请求的响应开始:

InputStream responseInputStream = response.getEntityInputStream()
我需要gzip该响应,以便将其上载到s3并将其压缩保存:

this.s3.putObject(new PutObjectRequest(bucketName, key, gzippedResponseInputStream, meta));
我知道我可以将byte[]数组从responseInputStream中取出,然后将它们gzip到新的InputStream中。但是,对于大量数据来说,这可能是非常低效的

我知道有人问过类似的问题,但我没有发现任何东西能够满足从InputStream开始到以Gzip InputStream结束的特定需求

谢谢你的帮助

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

}
你是对的,我之前的例子是错的。您可以使用管道流。这里的问题是不能使用来自同一线程的输入和输出流。也别忘了在书写线程上加入。您可以通过提供两个参数来测试我的示例:

args[0]->源文件 args[1]->写入压缩内容的目标 附言:@11thdimension使用管道流解决方案快了几分钟,所以如果你觉得这有帮助,请接受他的回答

你是对的,我之前的例子是错的。您可以使用管道流。这里的问题是不能使用来自同一线程的输入和输出流。也别忘了在书写线程上加入。您可以通过提供两个参数来测试我的示例:

args[0]->源文件 args[1]->写入压缩内容的目标
注:@11thdimension使用管道流解决方案快了几分钟,因此如果您觉得这有帮助,请接受他的回答

我想您正在寻找

以下是如何做到这一点

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

我还没有测试过这段代码,请告诉我这是否有效。

我想您正在寻找

以下是如何做到这一点

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

我还没有测试过这段代码,请告诉我这是否有效。

GZIPInputStream用于获取已经压缩的数据并对其进行解压缩。事实上,在意识到这一点之前,我已经试过了。但是,它在文档中也清楚地说明了这一点。感谢您的快速回复,但这是不正确的。谢谢@svetlin,我最后使用了您在问题评论中找到的解决方案,但我对此表示赞赏,我相信它是有效的,因此我将其标记为已接受。gzip输入流用于获取已压缩的数据并对其进行解压缩。事实上,在意识到这一点之前,我已经试过了。但是,它在文档中也清楚地说明了这一点。感谢您的快速回复,但这是不正确的。谢谢@svetlin我最终采用了您在对问题的评论中找到的解决方案,但我对此表示感谢,我相信它是有效的,因此我会将其标记为已接受。您是否检查了此答案?哇,谢谢你@SvetlinZarev-真管用!我一直在寻找我找到的每一个解决方案,但到目前为止,没有一个有效,但是你的建议成功了!非常感谢。你核对过这个答案了吗?哇,谢谢你@SvetlinZarev-真管用!我一直在寻找我找到的每一个解决方案,但到目前为止,没有一个有效,但是你的建议成功了!非常感谢。它赢了;t工作,因为当您退出try主体时,您将关闭pis,因此您将返回一个关闭的流;我也在想同样的事情。安全局是否尝试在方法结束时关闭流?无论如何,我将修改代码以使用它。更改后,至少现在不应该有封闭流问题。谢谢,如果其他解决方案有任何困难,我将尝试一下。我感谢大家的快速反应,我相信这对其他人也会有帮助;t工作,因为当您退出try主体时,您将关闭pis,因此您将返回一个关闭的流;我也在想同样的事情。安全局是否尝试在方法结束时关闭流?无论如何,我将修改代码以使用它。更改后,至少现在不应该有封闭流问题。谢谢,如果其他解决方案有任何困难,我将尝试一下。我感谢快速的响应,我相信这对其他人也会有用。