从一维条码中读取的键值对的有效压缩和表示

Posted

技术标签:

【中文标题】从一维条码中读取的键值对的有效压缩和表示【英文标题】:Efficient compression and representation of key value pairs to be read from 1D barcodes 【发布时间】:2013-02-22 13:06:29 【问题描述】:

我目前正在为 Windows Mobile 编写一个应用程序,该应用程序需要能够从一维条形码(配置设置)中提取键值对。需要扫描的条码越少越好。示例输入:

------------------------------
| Key | Value                |    
------------------------------
| 12  | Söme UTF-8 Strîng    |
|  9  | & another string     |
------------------------------

我想到了以下算法:

1.连接键值对并使用 Base64 编码值

所以我们会得到类似12=U8O2bWUgVVRGLTggU3Ryw65uZw==&9=JiBhbm90aGVyIHN0cmluZw==

2。使用霍夫曼编码压缩数据

我会为此使用固定的 Huffman 树,并提供以下信息来帮助我压缩数据:

-------------------------------------------
| Enties                       | Priority |    
-------------------------------------------
| =, &                         | High     |
| 0-9                          | Medium   |
| 5-bit Base64 Words (w/o 0-9) | Low      |
-------------------------------------------

3.从编码数据生成 Code 128B 条码

将 Base96 编码应用于 Huffman 算法生成的比特流,以获得可在 Code 128B 条码中使用的 ASCII 字符。根据需要将生成的字符串拆分为多个条形码。

编写这个步骤对我来说不是问题,但我想对算法的效率和设计有一些反馈。

问题

我是否在某处失去了更好压缩/更短字符串的潜力? 有没有更好的方法来压缩随机 UTF8 编码的数据? 是否应该将动态霍夫曼表嵌入到编码数据中? 如何考虑 Code 128B 的压缩(0 需要的空间比 & 少)?

【问题讨论】:

【参考方案1】:

一种简单的方法是定义所有 64 个字符,直接映射到 code128。这将留下 30-40 个可用代码 128 个插槽。在剩余的插槽中定义一些双字符。 == =& 0= 1= 2= 3= 4= 5= 6= 7= 8= 9= &0 &1 &2 &2 &5 &5 &6 &7 &8 &9 (重复最后一个字符)= =(双下一个字符) &(双下一个字符)

【讨论】:

【参考方案2】:

玩了好久,我们终于选择了这种方式:

1.将设置编码为字节流

字段值被序列化为字节流,每个字段都有一个标头。标头占用一个字节并包含字段的 ID 和一些有助于减少要传输的数据量的标志。根据字段的类型(例如字符串、数字或 IP 地址),该值被有效地编码到字节流中。例如,IP 地址用 4 个字节编码,而布尔标志直接编码到字段头中。这样,如果需要,我们甚至可以将 SSL 证书编码到流中。由于典型的条形码格式无法传输任意字节值,我们需要在下一步中对字节流进行编码。

2。转换成条码格式

生成的字节数组现在被视为一个大整数,并使用基本编码和字符集转换为目标条形码格式(请参阅this question)。这样,我们有效地使用条形码格式来传输我们的数据(与 Base64 或其他编码相反)。从生成的字符串中,我们可以将单个条形码大块并添加一些额外的标题信息(例如,必须扫描多少个条形码?数据是否加密?...)。

在移动设备上扫描条形码时,可以恢复编码字符串并将其转换为相同的大整数。然后可以将该整数视为字节数组,当字段序列化格式已知时可以对其进行解析。

事实证明,这种方法非常高效且快速(我们对 CF 上的 BigInteger implementation 存在一些担忧)。

【讨论】:

有关基本示例实现,请参阅***.com/questions/50343973/…【参考方案3】:

虽然某些条形码格式具有一组固定的字符,但它们可以表示并使用相同数量的空间来保存每个字符,而其他条形码格式要么使用多个字符集,要么使用可变数量的空间来保存每个字符。例如,“经典”代码 39 定义了 43 个字符,每个字符由 43 个符号之一表示,并且根本不能表示任何其他字符,但是还有另一个代码 39 变体,它使用一个符号表示 39 个常见字符,其他字符使用两个字符序列。例如,假设有人想将一堆二进制数据存储在 code-39 条形码中。如果将数据转换为 base-64 格式,与三个八位字节的原始数据相关联的四个字符可能平均需要大约 5.69 个符号来存储 [base64 中使用的 64 个字符中约有 27 个需要两个符号来存储在代码 39]。如果改为选择 32 个字符,每个字符可以用一个符号表示,则可以使用五个八位字节存储 24(或 25)位,每个八位字节存储五个位[一致的每个八位字节 1.67 个符号,而平均值为 1.89,最坏情况为 2.67 ]。如果使用“经典”代码 39(每个使用一个符号可以表示 43 个字符),甚至可以在六个符号中存储四个八位字节[平均每个八位字节 1.5 个符号]。

针对不同的字符集“优化”了不同的条码格式;有些像 Code 128 有多个字符集,并且可以有效地与使用一个字符集的全部范围的数据一起使用,同时避免使用它之外的字符。我不知道有什么特别推荐的方法来重新格式化数据以优化特定符号系统字符集的使用,但是检查符号系统使用的编码和您的特定要求应该可以帮助您找出最适合您的编码应用。

【讨论】:

以上是关于从一维条码中读取的键值对的有效压缩和表示的主要内容,如果未能解决你的问题,请参考以下文章

java问题,我想在java中存储键值对,以便使用,但是键值对的键和值都有重复元素,使用hashmap会产生覆盖。

如何解析没有分隔符的键值对的字符串?

如何计算 JQ 中每个对象的键值对的出现次数?

用于聚合键包含数字的键值对的算法

如何在 Swift 中实现一个管理 UserDefaults 的键值对的通用结构?

无法从日志文件中提取准确的键值对