我使用java.util.zip.Deflater来压缩通过HTTP PUT接收的数据流,这意味着我得到的数据用点滴和单调压缩,不是一次全部压缩。 调用java.util.zip.Deflater.setInput多次在第一次之后什么也不做
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请求处理程序反复调用,看起来像这样的方法从HTTP请求收到最后一个字节,我附加CRC和来自crc
和byteCount
实例变量的总未压缩长度。
只要我在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](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/zip/DeflaterOutputStream.java#119 )? (并且直接使用这个类会有意义吗?) – jtahlborn
正如jtahlborn所说,DeflaterOutputStream会大大地帮助。作为一般性评论,如果您使用'ArrayList.addAll(Arrays.asList(tempOutput))'而不是自己完成所有数组操作,那么您的代码看起来会更简单。 –
@jtahlborn,不,据我所知,没有办法让我使用DeflatorOutputStream,因为我没有输出流写入。我可能应该提到我的服务是使用[Vert.x](http://vertx.io)构建的,所以我正在从[ReadStream](http://vertx.io/docs/apidocs/index .html?io/vertx/core/streams/ReadStream.html)并写入[AsyncFile](http://vertx.io/docs/apidocs/index.html?io/vertx/core/file/AsyncFile.html )。数据从字节缓冲区中的ReadStream接收并写入字节缓冲区中的AsyncFile。没有输入或输出流。 –