1 前言
在RPC通信數據的傳輸場景下,當通信報文數據傳輸較大時,會對數據包進行壓縮傳輸,根據不同傳輸場景,常用的壓縮算法有Zlib、Gzip、Bzip2、Deflater、Lz4、Lzo、Snappy算法等。以下將包括算法的介紹、Java實現代碼以及各算法間的模擬性能對比。
2 壓縮方案
- Zlib
bzip2是Julian Seward開發并按照自由軟件/開源軟件協議發布的數據壓縮算法及程序。對于壓縮和解壓縮,沒有數據長度的限制,bzip2比傳統的gzip的壓縮效率更高,但是它的壓縮速度較慢。
核心代碼:
@Override
public byte[] compress(byte[] data) throws IOException {
byte[] output;
Deflater compresser = new Deflater();
compresser.reset();
compresser.setInput(data);
compresser.finish();
ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length);
try {
byte[] buf = new byte[1024];
while (!compresser.finished()) {
int i = compresser.deflate(buf);
bos.write(buf, 0, i);
}
output = bos.toByteArray();
} catch (Exception e) {
output = data;
e.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
compresser.end();
return output;
}
@Override
public byte[] uncompress(byte[] data) throws IOException {
byte[] output;
Inflater decompresser = new Inflater();
decompresser.reset();
decompresser.setInput(data);
ByteArrayOutputStream o = new ByteArrayOutputStream(data.length);
try {
byte[] buf = new byte[1024];
while (!decompresser.finished()) {
int i = decompresser.inflate(buf);
o.write(buf, 0, i);
}
output = o.toByteArray();
} catch (Exception e) {
output = data;
e.printStackTrace();
} finally {
try {
o.close();
} catch (IOException e) {
e.printStackTrace();
}
}
decompresser.end();
return output;
}
測試結果:
- Gzip
gzip的實現算法還是deflate,只是在deflate格式上增加了文件頭和文件尾,同樣jdk也對gzip提供了支持,分別是GZIPOutputStream和GZIPInputStream類,同樣可以發現GZIPOutputStream是繼承于DeflaterOutputStream的,GZIPInputStream繼承于InflaterInputStream,并且可以在源碼中發現writeHeader和writeTrailer方法。
核心代碼:
@Override
public byte[] compress(byte[] data) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip;
try {
gzip = new GZIPOutputStream(out);
gzip.write(data);
gzip.close();
} catch (IOException e) {
e.printStackTrace();
}
return out.toByteArray();
}
@Override
public byte[] uncompress(byte[] data) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(data);
try {
GZIPInputStream ungzip = new GZIPInputStream(in);
byte[] buffer = new byte[2048];
int n;
while ((n = ungzip.read(buffer)) >= 0) {
out.write(buffer, 0, n);
}
} catch (IOException e) {
e.printStackTrace();
}
return out.toByteArray();
}
測試結果:
- Bzip2
bzip2是Julian Seward開發并按照自由軟件/開源軟件協議發布的數據壓縮算法及程序。Seward在1996年7月第一次公開發布了bzip2 0.15版,在隨后幾年中這個壓縮工具穩定性得到改善并且日漸流行,Seward在2000年晚些時候發布了1.0版。bzip2比傳統的gzip的壓縮效率更高,但是它的壓縮速度較慢。
核心代碼:
@Override
public byte[] compress(byte[] data) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
BZip2CompressorOutputStream bcos = new BZip2CompressorOutputStream(out);
bcos.write(data);
bcos.close();
return out.toByteArray();
}
@Override
public byte[] uncompress(byte[] data) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(data);
try {
@SuppressWarnings("resource")
BZip2CompressorInputStream ungzip = new BZip2CompressorInputStream(in);
byte[] buffer = new byte[2048];
int n;
while ((n = ungzip.read(buffer)) >= 0) {
out.write(buffer, 0, n);
}
} catch (IOException e) {
e.printStackTrace();
}
return out.toByteArray();
}
測試結果:
- Deflater
DEFLATE是同時使用了LZ77算法與哈夫曼編碼(Huffman Coding)的一個無損數據壓縮算法,DEFLATE壓縮與解壓的源代碼可以在自由、通用的壓縮庫zlib上找到,zlib官網:http://www.zlib.net/ jdk中對zlib壓縮庫提供了支持,壓縮類Deflater和解壓類Inflater,Deflater和Inflater都提供了native方法。
核心代碼:
@Override
public byte[] compress(byte[] data) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Deflater compressor = new Deflater(1);
try {
compressor.setInput(data);
compressor.finish();
final byte[] buf = new byte[2048];
while (!compressor.finished()) {
int count = compressor.deflate(buf);
bos.write(buf, 0, count);
}
} finally {
compressor.end();
}
return bos.toByteArray();
}
@Override
public byte[] uncompress(byte[] data) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Inflater decompressor = new Inflater();
try {
decompressor.setInput(data);
final byte[] buf = new byte[2048];
while (!decompressor.finished()) {
int count = decompressor.inflate(buf);
bos.write(buf, 0, count);
}
} catch (DataFormatException e) {
e.printStackTrace();
} finally {
decompressor.end();
}
return bos.toByteArray();
}
測試結果:
- Lz4
LZ4是一種無損數據壓縮算法,著重于壓縮和解壓縮速度。
核心代碼:
@Override
public byte[] compress(byte[] data) throws IOException {
LZ4Factory factory = LZ4Factory.fastestInstance();
ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
LZ4Compressor compressor = factory.fastCompressor();
LZ4BlockOutputStream compressedOutput = new LZ4BlockOutputStream(byteOutput, 2048, compressor);
compressedOutput.write(data);
compressedOutput.close();
return byteOutput.toByteArray();
}
@Override
public byte[] uncompress(byte[] data) throws IOException {
LZ4Factory factory = LZ4Factory.fastestInstance();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
LZ4FastDecompressor decompresser = factory.fastDecompressor();
LZ4BlockInputStream lzis = new LZ4BlockInputStream(new ByteArrayInputStream(data), decompresser);
int count;
byte[] buffer = new byte[2048];
while ((count = lzis.read(buffer)) != -1) {
baos.write(buffer, 0, count);
}
lzis.close();
return baos.toByteArray();
}
測試結果:
- Lzo
LZO是致力于解壓速度的一種數據壓縮算法,LZO是Lempel-Ziv-Oberhumer的縮寫,這個算法是無損算法。
核心代碼:
@Override
public byte[] compress(byte[] data) throws IOException {
LzoCompressor compressor = LzoLibrary.getInstance().newCompressor(LzoAlgorithm.LZO1X, null);
ByteArrayOutputStream os = new ByteArrayOutputStream();
LzoOutputStream cs = new LzoOutputStream(os, compressor);
cs.write(data);
cs.close();
return os.toByteArray();
}
@Override
public byte[] uncompress(byte[] data) throws IOException {
LzoDecompressor decompressor = LzoLibrary.getInstance().newDecompressor(LzoAlgorithm.LZO1X, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayInputStream is = new ByteArrayInputStream(data);
@SuppressWarnings("resource")
LzoInputStream us = new LzoInputStream(is, decompressor);
int count;
byte[] buffer = new byte[2048];
while ((count = us.read(buffer)) != -1) {
baos.write(buffer, 0, count);
}
return baos.toByteArray();
}
測試結果:
- Snappy
Snappy(以前稱Zippy)是Google基于LZ77的思路用C++語言編寫的快速數據壓縮與解壓程序庫,并在2011年開源。它的目標并非最大壓縮率或與其他壓縮程序庫的兼容性,而是非常高的速度和合理的壓縮率。
核心代碼:
@Override
public byte[] compress(byte[] data) throws IOException {
return Snappy.compress(data);
}
@Override
public byte[] uncompress(byte[] data) throws IOException {
return Snappy.uncompress(data);
}
測試結果:
3 性能對比
ENV:JDK:11/CPU:4C/
不同大小文件壓縮效率及質量有差異,性能對比僅供參考;
Compress Rate(%) = Size Before(byte) / Size After(byte) * 100%
源碼地址
上傳至Gitee倉庫:
https://gitee.com/javanoteany/compress.git
-
通信數據
+關注
關注
0文章
13瀏覽量
9975 -
RPC
+關注
關注
0文章
111瀏覽量
11539 -
數據包
+關注
關注
0文章
261瀏覽量
24398
發布評論請先 登錄
相關推薦
評論