Java中的LZMA流

先介绍一下LZMA,部分译自LZMA Streams in Java:

Lempel-Ziv Markov-chain算法是一种相对较快且有效的压缩技术,用于7-zip压缩工具进行7z格式的压缩。该算法的实现有很多,包括C/C++,Java,C#,Python等其他语言。

为了实现一个高并发大数据量的网络传输系统,因此要用到数据压缩技术。Java里面对过滤输出流(FilterOutputStreams)有一个不成文标准,流明显要经过压缩或者数据加密等方式传输给他们(FilterInputStreams就做相反的事,解密或者解压数据)。不幸的是7Z的实现好像并没有提及这一点,而是另一种完全不同(近于白痴。。)的方式。

于是,net.contrapunctus.lzma包提供了一个LZMA输入输出流,用于与底层的LZMA编码解码器在不同的线程里相互作用。这样一来我就可以用我想要的接口,而不是去重构LZMA的实现。

注意:这些流与7-Zip文件是不兼容的,7z格式是一种包含多文件(以及元数据)且每个都是单独使用LZMA进行压缩的集合体。这些流支持这类压缩但不支持打包的格式?这跟GZipInputStream打不开zip格式的文件是一个道理,也即是说,它支持数据压缩成二进制文件,但不支持压缩包格式的构建。还有一些仅用于压缩的命令行工具,与LZMA流也是兼容的。

——————————————分水岭——————————————

OK,下面是一个Java中各种压缩算法实现的测试程序,简单比较了LZMA(7z),Gzip,Bzip,LZMA2(XZ)的区别。其中用到了两个7z的实现,

分别是: LZMA Streams in Javahttps://github.com/jponge/lzma-java

import lzma.sdk.lzma.Encoder;
import net.contrapunctus.lzma.LzmaOutputStream;
import org.apache.tools.bzip2.CBZip2OutputStream;
import org.tukaani.xz.LZMA2Options;
import org.tukaani.xz.XZOutputStream;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.util.zip.GZIPOutputStream;

public class CompressTest {

	public static void main(String[] args) throws Exception {
		File f = new File("/Users/cc/Downloads/ifunboxmac.dmg");
		System.out.println(f.length());
		ByteArrayOutputStream[] baoss = new ByteArrayOutputStream[5];
		for (int i = 0; i < 5; i++)
			baoss[i] = new ByteArrayOutputStream();
		MemoryMXBean mb = ManagementFactory.getMemoryMXBean();
		OutputStream[] oss = {new LzmaOutputStream(baoss[0]), new GZIPOutputStream(baoss[1]), new CBZip2OutputStream(baoss[2]), new XZOutputStream(baoss[3], new LZMA2Options()), new lzma.streams.LzmaOutputStream(baoss[4], new Encoder())};
		for (int i = 0; i < oss.length; i++) {
			FileInputStream fis = new FileInputStream(f);
			long t = System.currentTimeMillis();
			byte[] bb = new byte[1024];
			long u = mb.getHeapMemoryUsage().getUsed();
			int length;
			while ((length = fis.read(bb)) > -1)
				oss[i].write(bb, 0, length);
			baoss[i].close();
			oss[i].close();
			fis.close();
			System.out.println(oss[i].getClass().getSimpleName() + "\t" + baoss[i].size() + " (byte)\t" + (System.currentTimeMillis() - t) + " (ms)\t" + (mb.getHeapMemoryUsage().getUsed() - u));
		}
	}
}

分别在我的PC机(winXP,4G,2.8GHz)和Mac(i3 2.4GHz,4G)上测试,比较结果显示Gzip耗时和压缩率以及内存占用整体最低,其中LZMA2的实现XZ的压缩率最高(在Mac下报内存溢出没得到结果),但是耗时相对较长,BZip相对表现最差。结果如下图所示(Mac下测试得出):

原文件大小:2564362 (byte)

LzmaOutputStream
2581178 (byte)
1125 (ms)
10399816
GZIPOutputStream
2547080 (byte)
193 (ms)
1311408
CBZip2OutputStream
2512327 (byte)
3122 (ms)
8250880
LzmaOutputStream
2341470 (byte)
1893 (ms)
8760880


参考:

测试:A Quick Benchmark: Gzip vs. Bzip2 vs. LZMA

Bzip2:bzip2 library from Apache Ant

XZ:http://tukaani.org/xz/java.html

你可能感兴趣的:(Java中的LZMA流)