网上介绍序列化压缩的用gzip比较多。写个测试代码,测试一下四种序列化方式:
- 无压缩
- zlib压缩
- gzip压缩
- zip压缩
测例结果显示压缩效果:gzip压缩 > zlib压缩 > zip压缩> 无压缩 测例结果显示压缩速度:zlib压缩> gzip压缩> zip压缩 = 无压缩 确实用gzip性价比比较高!
### zlib介绍
zlib是一个开源库,提供了在内存中压缩和解压的函数。zlib它的设计目标是处理单纯的数据(而不管数据的来源是什么)。
### gzip介绍
gzip是UNIX下的一种数据格式(.tar.gz)。gzip是在zlib之上,包了一层,在头和尾添加了一些额外的信息。 gzip是一种文件压缩工具(或该压缩工具产生的压缩文件格式),它的设计目标是处理单个的文件。gzip在压缩文件中的数据时使用的就是zlib。为了保存与文件属性有关的信息,gzip需要在压缩文件(.gz)中保存更多的头信息内容,而zlib不用考虑这一点。但gzip只适用于单个文件,所以我们在UNIX/Linux上经常看到的压缩包后缀都是.tar.gz或*.tgz,也就是先用tar把多个文件打包成单个文件,再用gzip压缩的结果。
### zip介绍
zip只是一种数据结构,跟rar同级别的。zip是适用于压缩多个文件的格式(相应的工具有PkZip和WinZip等),因此,zip文件还要进一步包含文件目录结构的信息,比gzip的头信息更多。但需要注意,zip格式可采用多种压缩算法,我们常见的zip文件大多不是用zlib的算法压缩的,其压缩数据的格式与gzip大不一样。 Java SDK提供了对上述三种压缩技术的支持:Inflater类和Deflater类直接用zlib库对数据压缩/解压缩,GZIPInputStream类和GZIPOutputStream类提供了对gzip格式的支持,ZipFile、ZipInputStream、ZipOutputStream则用于处理zip格式的文件。 所以,你应当根据你的具体需求,选择不同的压缩技术:如果只需要压缩/解压缩数据,你可以直接用zlib实现,如果需要生成gzip格式的文件或解压其他工具的压缩结果,你就必须用gzip或zip等相关的类来处理了。
测试代码
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.Inflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
public class TestCompressedSerializaion {
public static BigObject createBigObject() {
final int SIZE = 1 << 12;
int[] bigArray = new int[SIZE];
for (int i = 0; i < SIZE; ++i) {
bigArray[i] = (int) (Math.random() * 100);
}
return new BigObject(bigArray);
}
public static void serializeObject(Object obj, String flName) {
FileOutputStream fileOut = null;
ObjectOutputStream out = null;
try {
fileOut = new FileOutputStream(flName);
out = new ObjectOutputStream(fileOut);
out.writeObject(obj);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (Exception e) {
}
}
if (fileOut != null) {
try {
fileOut.close();
} catch (Exception e) {
}
}
}
}
public static Object deserializeObject(String flName) {
FileInputStream fileIn = null;
ObjectInputStream in = null;
Object res = null;
try {
fileIn = new FileInputStream(flName);
in = new ObjectInputStream(fileIn);
res = in.readObject();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (Exception e) {
}
}
if (fileIn != null) {
try {
fileIn.close();
} catch (Exception e) {
}
}
}
return res;
}
public static void testCompressedSerializaion(CompressType compressType,
BigObject bigObj) {
CompressedSerializaion.compressType = compressType;
String flName = compressType.name() + ".ser";
long beginTime = System.currentTimeMillis();
serializeObject(new CompressedSerializaion(bigObj), flName);
CompressedSerializaion obj = (CompressedSerializaion) deserializeObject(flName);
long usedTime = System.currentTimeMillis()-beginTime;
System.out.println(flName + " length:" + new File(flName).length()
+ " usedTime:"+usedTime
+ " serialization correctness:"+ bigObj.equals(obj.getBigObj()));
}
public static void main(String[] args) {
BigObject bigObj = createBigObject();
testCompressedSerializaion(CompressType.UNCOMPRESSED, bigObj);
testCompressedSerializaion(CompressType.ZLIB, bigObj);
testCompressedSerializaion(CompressType.GZIP, bigObj);
testCompressedSerializaion(CompressType.ZIP, bigObj);
}
}
enum CompressType {
UNCOMPRESSED, ZLIB, GZIP, ZIP
};
@SuppressWarnings("serial")
class BigObject implements Serializable {
private int[] bigArray;
public BigObject(int[] bigArray) {
this.bigArray = bigArray;
}
public int[] getBigArray() {
return bigArray;
}
public void setBigArray(int[] bigArray) {
this.bigArray = bigArray;
}
@Override
public int hashCode() {
return Arrays.hashCode(bigArray);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BigObject other = (BigObject) obj;
if (!Arrays.equals(bigArray, other.bigArray))
return false;
return true;
}
}
@SuppressWarnings("serial")
class CompressedSerializaion implements Serializable {
public static CompressType compressType = CompressType.UNCOMPRESSED;
private BigObject bigObj;
public CompressedSerializaion(BigObject bigObj) {
this.bigObj = bigObj;
}
public BigObject getBigObj() {
return bigObj;
}
public void setBigObj(BigObject bigObj) {
this.bigObj = bigObj;
}
@Override
public int hashCode() {
return bigObj == null 0 : bigObj.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CompressedSerializaion other = (CompressedSerializaion) obj;
if (!bigObj.equals(other.bigObj))
return false;
return true;
}
public void writeMyObject(ObjectOutputStream out) throws IOException {
out.writeObject(bigObj);
}
private void readMyObject(ObjectInputStream ois)
throws ClassNotFoundException, IOException {
bigObj = (BigObject) ois.readObject();
}
private void writeObject(ObjectOutputStream out) throws IOException {
if (compressType == CompressType.UNCOMPRESSED) {
writeMyObject(out);
} else if (compressType == CompressType.ZLIB) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream baOos = new ObjectOutputStream(baos);
writeMyObject(baOos);
baOos.flush();
baOos.close();
byte unCompressedBytes[] = baos.toByteArray();
baos.close();
Deflater compresser = new Deflater(Deflater.BEST_SPEED);
compresser.setInput(unCompressedBytes);
compresser.finish();
byte bytes[] = new byte[unCompressedBytes.length];
int nz = compresser.deflate(bytes);
out.writeInt(nz);
out.write(bytes, 0, nz);
} else {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (compressType == CompressType.GZIP) {
GZIPOutputStream gzos = new GZIPOutputStream(baos);
ObjectOutputStream gzOos = new ObjectOutputStream(gzos);
writeMyObject(gzOos);
gzOos.flush();
gzos.close();
} else {
ZipOutputStream zos = new ZipOutputStream(baos);
ZipEntry ze = new ZipEntry("testZipSerializaion");
zos.setLevel(Deflater.BEST_SPEED);
zos.putNextEntry(ze);
ObjectOutputStream zipOos = new ObjectOutputStream(zos);
writeMyObject(zipOos);
zipOos.flush();
zos.closeEntry();
zos.close();
}
byte bytes[] = baos.toByteArray();
int nz = baos.size();
baos.close();
out.writeInt(nz);
out.write(bytes, 0, nz);
}
}
private void readObject(ObjectInputStream ois)
throws ClassNotFoundException, IOException {
if (compressType == CompressType.UNCOMPRESSED) {
readMyObject(ois);
} else {
int nz = ois.readInt();
byte bytes[] = new byte[nz];
int totalSize = 0;
while (totalSize < nz) {
// attempt to read the entire buffer in a single read
int bytesRead = ois.read(bytes, totalSize, (nz - totalSize));
if (bytesRead == -1) // EOF
break;
totalSize += bytesRead;
}
if (compressType == CompressType.ZLIB) {
Inflater decompresser = new Inflater();
decompresser.setInput(bytes, 0, nz);
byte[] unCompressedBytes;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
byte[] buf = new byte[1024];
while (!decompresser.finished()) {
int i = decompresser.inflate(buf);
baos.write(buf, 0, i);
}
unCompressedBytes = baos.toByteArray();
} catch (DataFormatException e) {
throw new IOException(e);
} finally {
try {
baos.close();
decompresser.end();
} finally {
}
}
ByteArrayInputStream bais = new ByteArrayInputStream(
unCompressedBytes);
ObjectInputStream baOis = new ObjectInputStream(bais);
readMyObject(baOis);
bais.close();
} else if (compressType == CompressType.GZIP) {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
GZIPInputStream zis = new GZIPInputStream(bais);
ObjectInputStream zipOis = new ObjectInputStream(zis);
readMyObject(zipOis);
bais.close();
} else if (compressType == CompressType.ZIP) {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ZipInputStream zis = new ZipInputStream(bais);
// open first zip file entry
ZipEntry ze = zis.getNextEntry();
ObjectInputStream zipOis = new ObjectInputStream(zis);
readMyObject(zipOis);
bais.close();
}
}
}
}
测试结果
UNCOMPRESSED.ser length:16582 usedTime:14 serialization correctness:true
ZLIB.ser length:6108 usedTime:4 serialization correctness:true
GZIP.ser length:5682 usedTime:5 serialization correctness:true
ZIP.ser length:6254 usedTime:14 serialization correctness:true