在Java中有效压缩10-1000个字符的字符串?

时间:2011-04-04 02:38:28

标签: java compression

我需要将10到1000个字符的字符串(用已知但可变的语言编写)压缩成单独的UDP数据包。

Java中可用的哪些压缩算法非常适合此任务?

是否有可用的开源Java库?

4 个答案:

答案 0 :(得分:9)

“这取决于”。

我会从主要候选人开始:LZMA(“7-zip”),deflate(直接,zlib:deflate +小包装,gzip:deflate +略大的包装,zip: deflate +甚至更大的包装器),bzip2(我怀疑这在这里​​会很好,最适合相对较大的窗口),甚至可能是LZS之类的其他LZ *分支has an RFC for IP Payload compression但是......

...使用多种不同方法,根据实际数据和压缩/吞吐量 运行一些分析。 Java有GZIPOutputStream(“gzip包装中的deflate”)和DeflaterOutputStream(“普通deflate”,推荐使用gzip或zip“wrappers”)标准,并且有LZMA Java implementations(只需要压缩器) ,而不是容器)所以这些都应该是模拟的小事。

如果数据包之间存在规律性,那么可以使用它 - 例如构建缓存映射,Huffman表,或者仅修改其他算法之一的“窗口” - 但可能需要考虑数据包丢失和“解压缩”。通过走这条路线会增加更多的复杂性。有关帮助压缩机的更多想法可以在SO: How to find a good/optimal dictionary for zlib 'setDictionary' when processing a given set of data?找到。

此外,协议应该可以简单地“退回”零压缩,因为某些[特别小的随机]数据可能实际上不可压缩或可能"compress" to a larger size(zlib实际上有这种保护,但也有“包装器开销”,因此对于非常小的数据,它将更好地单独编码)。对于如此小的尺寸,压缩数据的“包装器”(例如gzip或zip)的开销也需要考虑在内。考虑到小于约100个字符的字符串数据,这一点尤为重要。

快乐的编码。


要考虑的另一件事是用于将字符推入输出流的编码。我首先从UTF-8开始,但这可能并不总是理想的。


请参阅SO: Best compression algorithm for short text strings建议SMAZ,但我不知道此算法将如何转移到unicode / binary。


还要考虑并非所有deflate(或其他格式)实现都是相同的。就小数据的效率而言,与第三方(比如JZlib)相比,我并不知道Java的标准deflate,但考虑Compressing Small Payloads [.NET]显示“相同压缩”格式的相当负数。文章也很好地结束了:

  
    

...无论如何压缩通常是最有益的,并确定哪个有效负载(压缩的或未压缩的有效负载)具有最小的大小,并包含一个小的令牌来指示是否需要解压缩。

         

我的最终结论:始终使用真实世界的数据进行测试并衡量效益,或者最终您可能会有点意外!

  

快乐的编码。这次是真的。

答案 1 :(得分:5)

最简单的方法是将一个GZIPOutputStream层叠在ByteArrayOutputStream之上,因为它是内置在JDK中的,使用

ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream zos = new GZIPOutputStream(baos);

zos.write(someText.getBytes());
zos.finish();
zos.flush();


byte[] udpBuffer = baos.toByteArray();

可能还有其他算法可以做得更好,但我先尝试一下,看看它是否符合您的需求,因为它不需要任何额外的罐子,并且做得非常好。

答案 2 :(得分:5)

大多数标准压缩算法在使用少量数据时效果不佳。通常有一个标题和一个校验和,压缩需要一些时间进行预热。即它根据已经看到的数据构建数据字典。

因此你可以找到

  • 小包可能更小或相同大小,没有压缩。
  • 简单的应用程序/协议特定压缩更好
  • 您必须为压缩算法提供预建的数据字典,并尽可能地删除标题。

我通常选择小数据包的第二个选项。

答案 3 :(得分:1)

短字符串/ url的良好压缩算法是lzw实现,它在java中并且可以很容易地移植到客户端gwt: https://code.google.com/p/lzwj/source/browse/src/main/java/by/dev/madhead/lzwj/compress/LZW.java

一些评论

  • 对于小字符串使用9位代码字长度(尽管您可以尝试哪种更好)。原始比率从1(非常小的字符串,压缩不大于原始字符串)到0.5(更大的字符串)
  • 在客户端gwt用于其他代码字长度的情况下,需要调整输入/输出处理以按字节工作,以避免在将位序列缓冲为long时出现错误,这是为js模拟的。

我将它用于客户端gwt中的复杂url参数编码,以及base64编码和autobean序列化到json。

upd:base64实现在这里:http://www.source-code.biz/base64coder/java 你必须改变它以使网址安全,即更改以下字符:

  • ' +' - > ' - '
  • ' /' - > '〜'
  • ' =' - > ' _'