首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何压缩InputStream并返回InputStream?

如何压缩InputStream并返回InputStream?
EN

Stack Overflow用户
提问于 2016-08-13 02:45:47
回答 2查看 938关注 0票数 1

我从一个HTTP请求的响应开始:

代码语言:javascript
复制
InputStream responseInputStream = response.getEntityInputStream()

我需要对响应进行gzip压缩,这样我就可以将其上传到s3并压缩保存:

代码语言:javascript
复制
this.s3.putObject(new PutObjectRequest(bucketName, key, gzippedResponseInputStream, meta));

我知道我可以从responseInputStream中获得byte[]数组,然后将它们压缩到一个新的InputStream中。然而,对于大量的数据,这可能是非常低效的。

我知道在SO上也有类似的问题,但我还没有找到任何东西来解决从InputStream开始,以压缩的InputStream结束的特定需求。

谢谢你的帮助!

EN

回答 2

Stack Overflow用户

发布于 2016-08-13 02:50:50

代码语言:javascript
复制
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()。您可以通过提供两个参数来测试我的示例:

  • args ->源文件
  • args1 ->要写入压缩内容的目标

PS:@11thdimension比他的管道流解决方案快了几分钟,所以如果你觉得这对你有帮助,请接受他的回答

票数 3
EN

Stack Overflow用户

发布于 2016-08-13 03:49:50

我想你要找的是PipedInputStream

以下是如何做到这一点。

代码语言:javascript
复制
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();
        }
    }
}

我还没有测试过这段代码,请让我知道这是否可以工作。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38924585

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档