我的Java程序需要通过QR Code发送二进制有效载荷,但我无法让它工作。我尝试了几个QR Code库和许多方法,但似乎都有这个问题。我目前的实现使用ZXING。
问题是,我尝试过的所有Java库似乎都专注于String有效载荷,并且不提供对二进制数据的支持。对此,通常建议的solution是将二进制数据编码为Base64。然而,我的数据已经接近QR码的大小限制。由于Base64编码导致的4倍膨胀,我的数据太大了,我已经花费了大量的精力来减少有效载荷的大小,它目前由4个字符的散列组成,并由新的行分隔;都是在Java的压缩类的最大压缩级别里面的。我不能把它再小了。
我需要一种方法来存储二进制数据在QR码与最小的数据膨胀开销。
1条答案
按热度按时间doinxwow1#
我开发了一个解决方案,它只会带来-8%的存储效率损失,它利用了中兴QR码库的内置压缩优化。
ZXING会自动检测你的字符串负载是否是纯字母数字的(根据他们自己的定义),如果是,它会自动压缩2个字母数字字符到11位。ZXING使用的"字母数字"的定义是全大写,0 - 9,和一些特殊符号('/',':'等)。总的来说,他们的定义允许45个可能的值。然后,它把这些Base45数字中的2个压缩到11位。
以45为基数的2位是2,025个可能值。11位具有2,048个可能状态的最大存储容量。这仅比原始二进制损失1.1%的存储效率。
然而,这是理想的/理论上的效率。我的实现以块为单位处理数据,使用Long作为计算缓冲区。然而,由于Java Long是有符号的,我们只能使用较低的7个字节。转换代码需要连续的正值;使用最高的第8字节将污染符号位并随机产生负值。
真实世界测试:
使用一个7字节的长整型来编码一个2KB的随机字节缓冲区,我们得到以下结果。
实际存储效率损失仅为8%。
我将它实现为一个自包含的静态实用程序类,因此您所要做的就是调用:
或者,您也可以通过InputStreams完成此操作:
下面是实现
下面是我为验证代码而运行的一些测试: