博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Better Java GZIP Compression
阅读量:6938 次
发布时间:2019-06-27

本文共 3598 字,大约阅读时间需要 11 分钟。

April 30, 2010

I’ve been extending an HTTP server I maintain, and have run into a problem. To compress the response HTTP message contents I use the excellent GZIPOutputStream in the standard Java API. However, recently I have needed fine grain control over the trade-off between compression level and CPU usage on a particularly high load server. To my surprise the GZIPOutputStream class does not allow the compression level to be specified.

I set out to discover whether it was possible to customise the level of compression provided by GZIPOutputStream. The impatient can skip to the end of this post to get the answers, but the really interesting bit comes next.

First I took a look at the source code behind GZIPOutputStream. It turns out that it is little more than a Deflater in disguise:

public class GZIPOutputStream extends DeflaterOutputStream {
    ...
    public GZIPOutputStream(OutputStream out, int size) throws IOException {
        super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size);
        usesDefaultDeflater = true;
        writeHeader();
        crc.reset();
    }
    ...
}

The important part to notice in the code above is: new Deflater(Deflater.DEFAULT_COMPRESSION, true). Here a new Deflater instance is being created with a hard coded compression level of Deflater.DEFAULT_COMPRESSION. Not a very flexible design, but it does reveal that the compression level can be customised.

According to the Java API documentation the Deflater class has a method void setLevel(int level) that allows the compression level to be specified. The compression level must be between 0 and 9. A little arbitrary maybe, but along the lines of what I need (and this API was introduced in Java 1.1).

Moving up the ancestor chain I took a look at DeflaterOutputStream

public class DeflaterOutputStream extends FilterOutputStream {
    /**
     * Compressor for this stream.
     */
    protected Deflater def;
    ...
    public DeflaterOutputStream(OutputStream out, Deflater def, int size) {
        ...
        this.def = def;
        ...
    }
}

The deflater instance ends up as a variable def in the DeflaterOutputStream class. Although this is well hidden I had two things in my favour: firstly the def variable has protected access, and secondly the GZIPOutputStream is not declared final. This means that any subclass of GZIPOutputStream would have access to def. The two most practical solutions I can think of are presented below:

Instance Initialiser

One way to specify the GZIP compression level is to use the so called double brace initialisation. This is quick and easy, and useful if you only need to do it once or twice. Take a look at the following snippet:

GZIPOutputStream gzip = new GZIPOutputStream(output) {
    {
        def.setLevel(Deflater.BEST_COMPRESSION);
    }
};

In this example the first brace creates a new anonymous inner class and the second declares an instance initializer block that is run when the anonymous inner class is instantiated. This type of initializer block is formally called an instance initializer. In the example the compression is overridden to Deflater.BEST_COMPRESSION.

Subclass

The instance initialiser approach is useful when using GZIPOutputStream as a one-off, but for a more substantial solution it is better to inherit from GZIPOutputStream and create a useful subclass:

final class MyGZIPOutputStream extends GZIPOutputStream {
 
    public MyGZIPOutputStream(final OutputStream out) throws IOException {
        super(out);
    }
 
    public void setLevel(int level) {
        def.setLevel(level);
    }
}

In this example the void setLevel(int level) method can be used to directly influence the compression level after the GZIP output stream has been instantiated.

转载地址:http://zqinl.baihongyu.com/

你可能感兴趣的文章
前端开发中的一些用户体验细节
查看>>
第二章:身份验证
查看>>
开发基础(练习题)
查看>>
常用的HTTP响应头
查看>>
PYTHON2.day06
查看>>
http 响应码
查看>>
查找并绘制轮廓[OpenCV 笔记XX]
查看>>
Git系列之一 --- git remote
查看>>
PHP 实现多服务器共享 SESSION 数据
查看>>
Linux系统信息查看命令大全
查看>>
Coursera机器学习编程作业Python实现(Andrew Ng)—— 1.2 Linear regression with multiple variables...
查看>>
Java源码分析-UUID
查看>>
Directx11教程(47) alpha blend(4)-雾的实现
查看>>
opengl 教程(12) 投影矩阵
查看>>
8086汇编——课堂笔记整理3
查看>>
Python批量修改文件名-后缀
查看>>
如何成为强大的程序员?(转)
查看>>
Codeforces Round #349 (Div. 2) C. Reberland Linguistics (DP)
查看>>
C语言中的字符串
查看>>
AngularJS 事件
查看>>