数据压缩算法的介绍-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


相关文章
|
8天前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
34 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
8天前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
15 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
1天前
|
算法 Java 数据处理
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。HashSet基于哈希表实现,提供高效的元素操作;TreeSet则通过红黑树实现元素的自然排序,适合需要有序访问的场景。本文通过示例代码详细介绍了两者的特性和应用场景。
13 6
|
3天前
|
机器学习/深度学习 人工智能 算法
"拥抱AI规模化浪潮:从数据到算法,解锁未来无限可能,你准备好迎接这场技术革命了吗?"
【10月更文挑战第14天】本文探讨了AI规模化的重要性和挑战,涵盖数据、算法、算力和应用场景等方面。通过使用Python和TensorFlow的示例代码,展示了如何训练并应用一个基本的AI模型进行图像分类,强调了AI规模化在各行业的广泛应用前景。
13 5
|
1天前
|
Java
Java Set以其“不重复”的特性,为我们提供了一个高效、简洁的处理唯一性约束数据的方式。
【10月更文挑战第16天】在Java编程中,Set接口确保集合中没有重复元素,每个元素都是独一无二的。HashSet基于哈希表实现,提供高效的添加、删除和查找操作;TreeSet则基于红黑树实现,不仅去重还能自动排序。通过这两个实现类,我们可以轻松处理需要唯一性约束的数据,提升代码质量和效率。
9 2
|
3天前
|
算法 Java 数据处理
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其独特的“不重复性”要求,彻底改变了处理唯一性约束数据的方式。
【10月更文挑战第14天】从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其独特的“不重复性”要求,彻底改变了处理唯一性约束数据的方式。本文深入探讨Set的核心理念,并通过示例代码展示了HashSet和TreeSet的特点和应用场景。
8 2
|
4天前
|
JSON JavaScript Java
在Java中处理JSON数据:Jackson与Gson库比较
本文介绍了JSON数据交换格式及其在Java中的应用,重点探讨了两个强大的JSON处理库——Jackson和Gson。文章详细讲解了Jackson库的核心功能,包括数据绑定、流式API和树模型,并通过示例演示了如何使用Jackson进行JSON解析和生成。最后,作者分享了一些实用的代码片段和使用技巧,帮助读者更好地理解和应用这些工具。
在Java中处理JSON数据:Jackson与Gson库比较
|
6天前
|
缓存 安全 Java
使用 Java 内存模型解决多线程中的数据竞争问题
【10月更文挑战第11天】在 Java 多线程编程中,数据竞争是一个常见问题。通过使用 `synchronized` 关键字、`volatile` 关键字、原子类、显式锁、避免共享可变数据、合理设计数据结构、遵循线程安全原则和使用线程池等方法,可以有效解决数据竞争问题,确保程序的正确性和稳定性。
13 2
|
9天前
|
数据采集 XML 前端开发
Jsoup在Java中:解析京东网站数据
Jsoup在Java中:解析京东网站数据
|
1天前
|
缓存 Java 数据处理
java查询大量数据优化
通过结合的高性能云服务,如其提供的弹性计算资源与全球加速网络,可以进一步增强这些优化策略的效果,确保数据处理环节更加迅速、可靠。蓝易云不仅提供稳定的基础架构,还拥有强大的安全防护和灵活的服务选项,是优化大型数据处理项目不可或缺的合作伙伴。
6 0