java 反转InputStream/OutputStream(双向)操作[已关闭]

fxnxkyjh  于 2023-04-10  发布在  Java
关注(0)|答案(1)|浏览(158)

已关闭,此问题需要更focused,目前不接受回答。
**要改进此问题吗?**更新问题,使其仅关注editing this post的一个问题。

3天前关闭。
Improve this question
我观察到很多库只支持一个方向的流处理,比如压缩、加密等
GZIPInputStream/GZIPOutputStream假设您只会在读取时膨胀(* Package InputStream)和写入时收缩( Package OutputStream)。
同样,通过BouncyCastle的PGP的许多示例仅执行读取时解密(
再次, Package InputStream)和写入时加密( 再次, Package OutputStream
基于我在SO和其他地方遇到的混合示例,我试图编写一组通用实用程序函数,它将允许(
可能通过PipedInputStream/PipedOutputStream * 管道)支持双向流处理的能力,例如GZIP:

  • 读取时充气(* 支持开箱即用 *)
  • 写入时收缩(* 支持开箱即用 *)
    *Inflate on write(*missing;将压缩数据从套接字动态地膨胀到磁盘的示例用例 *)
    读取时放气 缺失;将未压缩数据从磁盘动态压缩到套接字的示例用例 *)

对于通过OutputStream处理运行InputStream的情况(deflate on write),以下代码工作:
(* 参见:IOUtils *)

static InputStream outputTransformingInputStream(InputStream inputStream, Function<OutputStream, OutputStream> transformer) {
    try {
        var pipedInputStream = new PipedInputStream();
        var pipedOutputStream = new PipedOutputStream(pipedInputStream);
        var transformerThread = new Thread(() -> {
            try (var transformerOutputStream = transformer.apply(pipedOutputStream)) {
                IOUtils.copy(inputStream, transformerOutputStream);
                transformerOutputStream.flush();
            } 
            catch (IOException exception) {
                throw new RuntimeException(exception);
            }
        });
        transformerThread.start();
        return pipedInputStream;
    }
    catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

与例如一起使用:

// Deflating when reading from an InputStream
var inflatedInputStream = new FileInputStream("/path/to/file.txt");
var deflatingInputStream = outputTransformingInputStream(inflatedInputStream, GZIPOutputStream::new);
var deflatedBytes = deflatingInputStream.readAllBytes(); // Works 👍

相反的方法不起作用(* 导致空的byte[]),也许这只是因为我盯着流和管道太久了,我已经把顺序搞砸了:
参见:IOUtils *)

static OutputStream inputTransformingOutputStream(OutputStream outputStream, Function<InputStream, InputStream> transformer) {
    try {
        var pipedOutputStream = new PipedOutputStream();
        var pipedInputStream = new PipedInputStream(pipedOutputStream);
        var transformerThread = new Thread(() -> {
            try (var transformingInputStream = transformer.apply(pipedInputStream)) {
                IOUtils.copy(transformingInputStream, outputStream);
                outputStream.flush();
            }
            catch (IOException exception) {
                throw new RuntimeException(exception);
            }
        });
        transformerThread.start();
        return pipedOutputStream;
    }
    catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

这个示例调用的结果是一个空的inflatedBytes

// Inflating when writing to an OutputStream
var inflatedOutputStream = new ByteArrayOutputStream();
var inflatingOutputStream = StreamFactory.inputTransformingOutputStream(inflatedOutputStream, GZIPInputStream::new);
inflatingOutputStream.write(deflatedBytes); // deflatedBytes previously deflated, see above
inflatingOutputStream.flush();
var inflatedBytes = inflatedOutputStream.toByteArray(); // Empty 👎

问题(S):

  • PipedInputStream/PipedOutputStream实用程序方法示例是泛化此功能的最佳方法吗?
  • 如果是这样,有人能告诉我在inputTransformingOutputStream函数中哪里出错了吗?
  • 如果没有,那么创建对双向流处理的通用支持的更好方法是什么?

所以我继续提到GZIP和inflate/deflate可能看起来这就是我想做的。
更一般地,给定对流数据进行单向转换的库FooBar

interface FooService {
     InputStream enfooify(InputStream inputStream);
     OutputStream defooify(OutputStream outputStream);
}

interface BarService {
    InputStream enbarify(InputStream inputStream);
    OutputStream debarify(OutputStream outputStream);
}

我正在尝试创建一个通用的解决方案:

少谈GZIP、PGP或其他什么特别的东西,多谈在库还没有支持通用双向流数据转换时支持通用双向流数据转换。

afdcj2ne

afdcj2ne1#

虽然我可以分享你的观察,但我不认为这有什么问题。让我们看看两个缺失的例子:

  • 写入时充气(缺失;将压缩数据从套接字动态地膨胀到磁盘的示例用例)
  • 读取时放气(缺失;将未压缩数据从磁盘即时压缩到套接字的示例用例)

在这两种情况下,你都需要读取数据,处理(inflate/deflate)和写入它。对于这三个步骤,无论你将处理移动到左侧(读取和inflate/deflate)还是右侧(inflate/deflate和write),效果都很小。出于同样的原因,它也没有什么影响,其中一个是左的,另一个是右的。
您完全可以使用现有的类构建您提到的用例。

相关问题