观察到很多库只支持一个方向的流处理,比如压缩、加密等
GZIPInputStream
/GZIPOutputStream
假设你只会在阅读时膨胀(包装InputStream
)和放气写(包装OutputStream
).
同样,许多通过 BouncyCastle 的 PGP 示例仅执行读取时解密(再次,包装
InputStream
)和写入时加密(再次,包装OutputStream
)
基于我在 SO 和其他地方遇到的混合示例,我正在尝试编写一组通用实用函数,这将允许(可能通过管道与
PipedInputStream
/PipedOutputStream
) 支持双向流处理的能力,例如使用 GZIP:
InputStream
处理运行 OutputStream
的情况(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 👎
所以,问题:
PipedInputStream
/PipedOutputStream
实用方法示例是泛化此功能的最佳方法吗?inputTransformingOutputStream
函数中哪里出错了吗?虽然我可以分享你的观察,但我看不出这里有什么问题。让我们看看两个缺失的例子:
在这两种情况下,您都需要读取数据、处理(膨胀/收缩)并写入数据。 对于这三个步骤,将处理移动到左侧(读取和膨胀/收缩)还是右侧(膨胀/收缩和写入)几乎没有影响。出于同样的原因,它也是一个很小的影响,其中一个是左的,另一个是右的。
您绝对可以使用现有类构建您提到的用例。