1.起因:
1.0 在《小别科技》这个项目中.存在一个需求,扫描商品的条形码,以登陆商品的入库信息.但是在Android的有一定概率扫描出的条形码是错误的.体现的效果就是扫描出的条形码指向了其他的商品.
1.1 这引起了我的思考,因为设备的和环境的因素导致扫描的结果与实际存在出入完全可以理解.但是条形码自身难道没有任何的纠错及校验机制吗?
1.2 先假设条形码本身无任何纠错及校验机制.那么假如在商场中有两个条形码很相近的物品A和B.
他们的条形码的区别仅在于A的低3条黑线是细的,而B的第三条黑线是粗的.其余部分均相同.而A的价格是¥1000 B的价格是¥10.
那么我们在商城购物的时候故意将A的条形码的第三条涂粗,是否就能骗过扫码的机器,只用付10元就能拿走A商品?
然而现实中在商城购买东西是会遇到扫不出码的情况,但却从未遇到扫错商品的情况.-
1.3 因此在条形码中应该存在一种保护机制,让扫条形码仅有下述1,2两种可能.
1.正确扫描出条形码
2.扫描的结果错误
3.扫描成其他商品
2.发现
- 2.1 这个问题的答案在《编码——隐匿在计算机软硬件背后的语言》书中找到了答案.
-
2.2 条形码UPC(universal product code).通常情况下是由30条不同宽度的垂直黑色条纹的集合,由不同宽度的间隔分隔开.
按区域划分
左侧空白区 | 起始符号 | 左侧数据符 | 中间分隔符 | 右侧数据符 | 校验符 | 终止符 | 右侧空白区 |
---|---|---|---|---|---|---|---|
2竖线 | 6位数字 | 2竖线 | 5位数字 | 1位数字 | 2竖线 |
-
2.3 实验:
下图是我随手找来的一包纸的UPC.
用代码生成二维码
-
2.4 字符编码规则
从左向右,第2位到第7位(6个数字)为左侧字符。左侧字符采用两种编码方式:A方式或B方式,编码表如下:
然后根据前置码(第一位)确定这6个字符的编码方式是A还是B。
前置码决定的编码方式如下表:
6931767054590的前置码为6,查上表,左侧6个数据的编码方式为ABBBAA。
右侧字符从第8个字符起到最后一位。均按照C方式编码。 2.5 开始转码
比特 | 含义 |
---|---|
101 | 左护线 |
0001011 | 左字符(编码A) 10进制:9 |
0100001 | 左字符(编码B) 10进制:3 |
0110011 | 左字符(编码B) 10进制:1 |
0010001 | 左字符(编码B) 10进制:7 |
0101111 | 左字符(编码A) 10进制:6 |
0111011 | 左字符(编码A) 10进制:7 |
01010 | 中间分隔符 |
1110010 | 右字符(编码C) 10进制:0 |
1001110 | 右字符(编码C) 10进制:5 |
1011100 | 右字符(编码C) 10进制:4 |
1001110 | 右字符(编码C) 10进制:5 |
1110100 | 右字符(编码C) 10进制:9 |
1110010 | 右字符(编码C) 10进制:0 |
101 | 右护线 |
所得结果为:931767054590 与条形码下的数字相同
3.校验:
- 3.1 奇偶校验
A子集下1的个数总为奇数,BC子集下1的个数总为偶数.
因此若在扫描的连奇偶校验都通不过则立即视为无效条形码. - 3.2 校验码:校验码为条形码10进制表达式下的最后一位数如6931767054590的校验码即为0;
1.将除最后一位的所有奇数位相加.
6 + 3 + 7 + 7 + 5 + 5 = 33
2.将除最后一位的所有偶数数位相加并x3.
(9 + 1 + 6 + 0 + 4 + 9) * 3 = 87
3.将上面两数相加并用10 减去相加数的个位数
校验码 = 10 - ((33 + 87) % 10) = 10 即为0;
因此校验码与结果相同 成功通过校验.