【发布时间】:2017-02-15 17:34:24
【问题描述】:
我正在使用 java.util.zip.Deflater 来压缩通过 HTTP PUT 接收的传入数据流,这意味着我将数据压缩成点点滴滴,而不是一次全部压缩。因此,当数据进入时,我的 HTTP 请求处理程序重复调用如下所示的方法:
byte[] compress(byte[] input) {
byte[] output = null;
if (this.compressor == null) {
this.compressor = new Deflater(Deflater.BEST_COMPRESSION, true);
// Add gzip header:
output = getGzipHeader();
}
this.compressor.setInput(input);
this.compressor.finish();
while (!this.compressor.finished()) {
byte[] tempOutput = new byte[10240];
int compressedLength = this.compressor.deflate(tempOutput);
if (output == null) {
output = Arrays.copyOf(tempOutput, compressedLength);
} else {
byte[] newOutput = Arrays.copyOf(output, output.length + compressedLength);
System.arraycopy(tempOutput, 0, newOutput, output.length, compressedLength);
output = newOutput;
}
}
// Update CRC:
this.crc.update(input);
this.byteCount += input.length;
return output
}
当然,包含这个方法的类也有实例变量:
private Deflater compressor;
private CRC32 crc = new CRC32();
private long byteCount = 0;
一旦从 HTTP 请求接收到最后一个字节,我会从 crc 和 byteCount 实例变量中附加 CRC 和总未压缩长度。
只要我在 HTTP PUT 中发送非常少量的数据,就可以很好地工作,因为 compress 方法只被调用一次。我最终得到了一个有效的 gzip 文件。一旦我发送超过几百个字节,导致compress 被多次调用,它就不起作用,因为在第一个之后对compress 的所有后续调用中,this.compressor.finished() 返回 true,即使我用新的输入数据调用了this.compressor.setInput(input)。如果我在处理完所有数据后查看this.compressor.getBytesRead(),则该调用返回的值正是传入的第一个输入缓冲区的大小(第一次调用this.compressor.setInput(input))。对该方法的后续调用都不会增加getBytesRead() 返回的值。
如果我在调用setInput() 之后不调用finish(),它根本不起作用——我没有得到任何输出。但似乎调用finish() 是在告诉Deflater 不要接受任何更多的输入。
我做错了什么?
【问题讨论】:
-
这有帮助吗:DeflaterOutputStream? (直接使用这个类有意义吗?)
-
正如 jtahlborn 所说,DeflaterOutputStream 会有很大帮助。作为一般性评论,如果您使用
ArrayList.addAll(Arrays.asList(tempOutput))而不是自己进行所有数组操作,您的代码看起来会简单得多。 -
@jtahlborn,不,据我所知,我无法使用 DeflatorOutputStream,因为我没有要写入的输出流。我可能应该提到我的服务是使用Vert.x 构建的,所以我从ReadStream 读取并写入AsyncFile。数据从字节缓冲区中的 ReadStream 接收并写入字节缓冲区中的 AsyncFile。没有输入或输出流。
-
@KlitosKyriacou,不,这将添加整个 tempOutput 缓冲区,包括所有 0 字节。我正在为手头的问题寻求帮助,能够基于读取输入数据流中的小块来编写压缩数据——我对一般的编码建议不感兴趣,谢谢。此代码已针对此帖子进行了简化,以试图清楚地说明具体问题。
-
您可以实现一个写入 AsyncFile 的 OutputStream。