Java / Scala的Deflator用于压缩BitSet的性能

时间:2014-06-25 19:36:37

标签: java scala compression

我有这个使用Java的Deflator / Inflator的Scala代码。

  def compress(bytes: Array[Byte]): Array[Byte] = {
    val deflater = new java.util.zip.Deflater
    val baos = new ByteArrayOutputStream
    val dos = new DeflaterOutputStream(baos, deflater)
    dos.write(bytes)
    baos.close
    dos.finish
    dos.close
    baos.toByteArray
  }

  def decompress(bytes: Array[Byte]): String /*Array[Byte]*/ = {
    val deflater = new java.util.zip.Inflater()
    val baos = new ByteArrayOutputStream(512)
    val bytesIn = new ByteArrayInputStream(bytes)
    val in = new InflaterInputStream(bytesIn, deflater)
    var go = true
    while (go) {
      val b = in.read
      if (b == -1)
        go = false
      else
        baos.write(b)
    }
    baos.close
    in.close
    // String(byte[] bytes, Charset charset)
    new String(baos.toByteArray, "ASCII")
  }

我需要压缩只有一位(来自13 x 8 = 104位的第100位)设置的BitSet。

val bs = new util.BitSet()
bs.set(100)
val ba = bs.toByteArray
val z = gzip.compress(ba)
println(ba.size)
println(ba.mkString(":"))
println(z.size)
println(z.mkString(":"))

我希望减少一些戏剧性的尺寸,但结果是我只保存了一个字节。

13
0:0:0:0:0:0:0:0:0:0:0:0:16
12
120:-100:99:96:64:0:1:0:0:29:0:17

这是Java解压缩器的预期结果吗?这种情况下有更好的压缩机吗?

2 个答案:

答案 0 :(得分:1)

我认为问题是GZIP编码数据包含占用字节的头信息。这并不重要,因为要压缩的数据大小通常要大得多。

如果你有大多数零(或任何相同值的运行)和几个字节的其他东西,也许运行长度编码更好。

如果你真的只有1位设置,那么你可以想出你自己的编码,如果bitSet是固定长度,它只编码那个单位的偏移。

答案 1 :(得分:1)

  

这是Java解压缩器的预期结果吗?

这是我所期待的。 " deflate"压缩算法是为压缩大文件而设计的。对于一个小文件(13个字节),编码中的开销可能会平衡(甚至超过)所实现的压缩。

  

这种情况有没有更好的压缩机?

我不希望标准Java库支持的任何压缩算法做得更好。如果你想在微小的位图上获得良好的性能,你可能需要从第一原理设计自定义压缩器。

例如,稀疏位图可以表示为数字序列(在本例中为byte值),表示已设置的位,或表示连续运行的数字序列或零。