序列化压缩实现及对比测试

网上介绍序列化压缩的用gzip比较多。写个测试代码,测试一下四种序列化方式:

  • 无压缩
  • zlib压缩
  • gzip压缩
  • zip压缩

测例结果显示压缩效果:gzip压缩 > zlib压缩 > zip压缩 > 无压缩

测例结果显示压缩速度:zlib压缩 > gzip压缩 > zip压缩 = 无压缩

确实用gzip性价比比较高!

zlib、gzip、zip介绍


1. zlib

zlib是一个开源库,提供了在内存中压缩和解压的函数。zlib它的设计目标是处理单纯的数据(而不管数据的来源是什么)。

   

2.  gzip

gzip是UNIX下的一种数据格式(.tar.gz)。gzip是在zlib之上,包了一层,在头和尾添加了一些额外的信息。

gzip是一种文件压缩工具(或该压缩工具产生的压缩文件格式),它的设计目标是处理单个的文件。gzip在压缩文件中的数据时使用的就是zlib。为了保存与文件属性有关的信息,gzip需要在压缩文件(*.gz)中保存更多的头信息内容,而zlib不用考虑这一点。但gzip只适用于单个文件,所以我们在UNIX/Linux上经常看到的压缩包后缀都是*.tar.gz或*.tgz,也就是先用tar把多个文件打包成单个文件,再用gzip压缩的结果。

   

3. 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
原文地址:https://www.cnblogs.com/firstdream/p/7793778.html