数据压缩算法的介绍-Java实现-对比

简介: 在RPC通信数据的传输场景下,当通信报文数据传输较大时,会对数据包进行压缩传输,根据不同传输场景,常用的压缩算法有Zlib、Gzip、Bzip2、Deflater、Lz4、Lzo、Snappy算法等。以下将包括算法的介绍、Java实现代码以及各算法间的模拟性能对比。

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;
    }

测试结果:


image.png


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();
  }

测试结果:


image.png


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();
  }

测试结果:


image.png


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();
  }

测试结果:


image.png


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();
  }

测试结果:


image.png


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();
  }

测试结果:


image.png


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);
  }

测试结果:


image.png


3 性能对比

ENV:JDK:11/CPU:4C/


image.png


不同大小文件压缩效率及质量有差异,性能对比仅供参考;


Compress Rate(%) = Size Before(byte) / Size After(byte) * 100%


源码地址


上传至Gitee仓库:


Gitee仓库源码


https://gitee.com/javanoteany/compress.git


相关文章
|
28天前
|
XML 数据采集 存储
使用Java和XPath在XML文档中精准定位数据
在数据驱动的时代,从复杂结构中精确提取信息至关重要。XML被广泛用于数据存储与传输,而XPath则能高效地在这些文档中导航和提取数据。本文深入探讨如何使用Java和XPath精准定位XML文档中的数据,并通过小红书的实际案例进行分析。首先介绍了XML及其挑战,接着阐述了XPath的优势。然后,提出从大型XML文档中自动提取特定产品信息的需求,并通过代理IP技术、设置Cookie和User-Agent以及多线程技术来解决实际网络环境下的数据抓取问题。最后,提供了一个Java示例代码,演示如何集成这些技术以高效地从XML源中抓取数据。
使用Java和XPath在XML文档中精准定位数据
|
8天前
|
存储 算法 测试技术
预见未来?Python线性回归算法:数据中的秘密预言家
【9月更文挑战第11天】在数据的海洋中,线性回归算法犹如智慧的预言家,助我们揭示未知。本案例通过收集房屋面积、距市中心距离等数据,利用Python的pandas和scikit-learn库构建房价预测模型。经过训练与测试,模型展现出较好的预测能力,均方根误差(RMSE)低,帮助房地产投资者做出更明智决策。尽管现实关系复杂多变,线性回归仍提供了有效工具,引领我们在数据世界中自信前行。
22 5
|
30天前
|
Java
【Java基础面试五】、 int类型的数据范围是多少?
这篇文章回答了Java中`int`类型数据的范围是-2^31到2^31-1,并提供了其他基本数据类型的内存占用和数值范围信息。
【Java基础面试五】、 int类型的数据范围是多少?
|
12天前
|
算法 Java
Java 压缩文件
在Java中压缩文件是一个常见的需求,通常可以通过使用Java自带的`java.util.zip`包来实现。这个包提供了`ZipOutputStream`类来创建ZIP格式的压缩文件。以下是一个简单的示例,展示了如何将多个文件压缩到一个ZIP文件中。 ### 示例:将多个文件压缩到一个ZIP文件中 ```java import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipFilesExample { public static vo
|
17天前
|
Java API 开发者
代码小妙招:用Java轻松获取List交集数据
在Java中获取两个 `List`的交集可以通过 `retainAll`方法和Java 8引入的流操作来实现。使用 `retainAll`方法更为直接,但会修改原始 `List`的内容。而使用流则提供了不修改原始 `List`、更为灵活的处理方式。开发者可以根据具体的需求和场景,选择最适合的方法来实现。了解和掌握这些方法,能够帮助开发者在实际开发中更高效地处理集合相关的问题。
14 1
|
17天前
|
编解码 算法 图形学
同一路RTSP|RTMP流如何同时回调YUV和RGB数据实现渲染和算法分析
我们播放RTSP|RTMP流,如果需要同时做渲染和算法分析的话,特别是渲染在上层实现(比如Unity),算法是python这种情况,拉两路流,更耗费带宽和性能,拉一路流,同时回调YUV和RGB数据也可以,但是更灵活的是本文提到的按需转算法期望的RGB数据,然后做算法处理
|
27天前
|
监控 Java 开发工具
【事件中心 Azure Event Hub】Event Hub Java SDK的消费端出现不消费某一个分区中数据的情况,出现IdleTimerExpired错误消息记录
【事件中心 Azure Event Hub】Event Hub Java SDK的消费端出现不消费某一个分区中数据的情况,出现IdleTimerExpired错误消息记录
|
26天前
|
存储 Java Apache
|
18天前
|
开发者 Java Spring
【绝技揭秘】掌握Vaadin数据绑定:一键同步Java对象,告别手动数据烦恼,轻松玩转Web应用开发!
【8月更文挑战第31天】Vaadin不仅是一个功能丰富的Java Web应用框架,还提供了强大的数据绑定机制,使开发者能轻松连接UI组件与后端Java对象,简化Web应用开发流程。本文通过创建一个简单的用户信息表单示例,详细介绍了如何使用Vaadin的`Binder`类实现数据绑定,包括字段与模型属性的双向绑定及数据验证。通过这个示例,开发者可以更专注于业务逻辑而非繁琐的数据同步工作,提高开发效率和应用可维护性。
38 0
|
26天前
|
固态存储 Java 网络安全
【Azure Developer】使用Java SDK代码创建Azure VM (包含设置NSG,及添加数据磁盘SSD)
【Azure Developer】使用Java SDK代码创建Azure VM (包含设置NSG,及添加数据磁盘SSD)