无法从条码中识别字符串编码

Unable to identify string encoding from barcode

我的任务是使用 iOS 设备解码存储在 Aztec 条形码上的数据。我可以访问组装发送到条码打印机的字符串的代码,但打印本身是一个黑盒子。

当我逐步执行该过程时,我可以看到发送到打印机的字符串如下所示(请注意,除前 8 个字符外,这是一个加密字符串):

_36_30_30_30_30_34_7c_5d_49_0b_ea_f7_93_ba_89_d2_c6_c2_41_2a_d7_1c_49_8c_6d_4b_5c_07_5a_ca_7a_6a_c6_d5_d0_6c_f7_20_76_5b_e0_18_46_93_7e_2a_30_0d_14_3a_1a_e5_66_7c_05_f9_df_96_8a_f1_45_a5_4a_6e_2f_89_3f_f0_93_1f_bc_3e_77_5b_27_0c_58_df_55_37_4c_ae_8a_e7_c3_c6_16_5b_57_db_7c_2d_2c_8b_1c_e3_a4_44_1b_c4_ba_6a_c6_98_93_ae_2d_20_6e_9f_e8_0f_eb_bc_9f_2e_8a_e7_cf_da_22_96_e1_74_de_b2_f0_29_ec_b1_c1_75_43_1f_b2_e5_1f_a5_f6_06_3e_97_a1_a1_93_f4_51_4a_c4_14_9f_1a_c2_5b_ba_02_45_44_2b_b3_c2_5b_ba_02_45_44_2b_b3_c2_5b_ba_02_45_44_2b_b3_c2_5b_ba_02_45_44_2b_b3_c2_5b_ba_02_45_44_2b_b3_c2_5b_ba_02_45_44_2b_b3_06_0b_12_75_85_8b_07_fb

打印的条形码如下所示:

但是,当我使用通用 iOS 条形码 reader 读回(我试过几次)时,我得到以下信息:

600004|]I�ê÷ºÒÆÂA*×�ImK\�ZÊzjÆÕÐl÷ v[à�F~*0
�:�åf|�ùßñE¥Jn/?ð�¼>w['�XßU7L®çÃÆ�[WÛ|-,�ã¤D�ĺjÆ®- nè�PÐk^¡±xOS5·Óþ�ßá×D¢\���¥ö�>¡¡ôQJÄ��Â[º�ED+³Â[º�ED+³Â[º�ED+³Â[º�ED+³Â[º�ED+³Â[º�ED+³���u�û

这与原始字符串很相似(例如前几个字符)。但我不知道这是什么类型的编码,也不知道如何将其转换为我期望看到的十六进制代码。

我很想知道:

1) 我在看什么?

2) 如何将此字符串转换回原始格式?

注意:为了清楚起见,您所说的加密字符串,我将其称为十六进制代码,以进一步区分 [=132] 末尾的随机字符串=].

总结

我相信您在字符串中看到的编码是错误的 ASCII/ISO-8859-1 编码。它省略了一些字符,因此无法从该字符串中恢复原始的十六进制代码。在找到可以正确处理条码的扫描仪后,发现条码与您的十六进制代码不匹配。

编码

Wikipedia says that by default1, byte codes in Aztec are interpreted as ASCII when between 0 and 127, and as ISO-8859-1 当介于 128 和 255 之间时。因此,当您将获得的字母和符号替换为来自这两种编码的正确十六进制值时,您将得到以下内容:

36 30 30 30 30 34 7C 5D 49 EA F7 BA D2 C6 C2 41 2A D7 49 6D 4B 5C 5A CA 7A 6A C6 D5 D0 6C F7 20 76 5B E0 46 7E 2A 30 0A 3A E5 66 7C F9 DF F1 45 A5 4A 6E 2F 3F F0 BC 3E 77 5B 27 58 DF 55 37 4C AE E7 C3 C6 5B 57 DB 7C 2D 2C E3 A4 44 C4 BA 6A C6 AE 2D 20 6E E8 50 D0 6B 5E A1 B1 78 4F 53 35 B7 D3 FE DF E1 D7 44 A2 5C

这类似于您的加密十六进制代码,但省略了一些字节,并且粗体 E8 字节之后的内容不同。省略的字节全部来自 00 - 1F80 - 9F 范围。 ASCII 中的 00 - 1F 范围是控制代码,其中大部分很少使用,也没有得到很多应用程序的很好支持。另一个范围在 ISO-8859-12 中未定义。因此,任何试图将这些字节解释为 ASCII/ISO-8859-1 字符串的应用程序都可能导致不可预知的行为。

如果您从加密的十六进制代码中的这些范围中删除字节,您基本上会得到 3 与我得到的相同的东西,直到 E8 字节。 E8 之后的字节是 0F。我以前从未听说过这个控制代码,但是 apparently 它叫做 "Shift In" 它的功能是 "Return to regular character set after Shift Out." 由于我们已经遇到字符集问题,我只能假设此控制代码负责 E8 字节后的解释错误。

编辑: 您最近的一项编辑修改了字符串,它现在包含以下几个字符:�。这是 Unicode 的替换字符,当出现字符编码问题或进程无法解释特定字符时,通常会替换其他字符。在本例中,它替换了 00 - 1F 范围内的许多字节,这些字节是 ASCII 控件。仍然无法恢复。 80 - 9F 范围仍然被省略。

更好的条码reader

为了正确解释条形码,您需要 reader 不将十六进制代码解释为编码字符串,而是解释为字节流。至少,您需要一个 reader 仍然保留 00 - 1F80 - 9F 范围。

我发现的 reader 是 NeoReader。您完全有可能已经尝试过,但是复制粘贴可能会导致这些特殊代码范围出现错误。

我在 iOS 7 设备上用它扫描了代码,然后点击应用程序提供的 "Copy to Clipboard" 按钮。然后,我将字符串粘贴到 this converter 的顶部并点击转换。我通常将此转换器用于 Unicode 内容,但我发现其他专用文本到十六进制转换器无法处理字符串及其特殊代码。如果向下滚动到 "Hexadecimal code points,",您应该能够看到所需的十六进制代码,尽管它们的前缀是额外的 004.

它生成的字符串(虽然我对它持保留态度,但我有一些复制粘贴错误,而且似乎在 post 编辑它时删除了特殊控件):

600004|]I ê÷ºÒÆÂA*×ImK\ZÊzjÆÕÐl÷ v[àF~*0 :åf|ùßñE¥Jn/?ð¼>w[' XßU7L®çÃÆ[WÛ|-,ã¤DĺjÆ®- nèPÐk^¡±xOS5·Óþßá×D¢\¥ö>¡¡ôQJÄÂ[ºED+³Â[ºED+³Â[ºED+³Â[ºED+³Â[ºED+³Â[ºED+³ uû

十六进制代码比较(不同之处用< >标示):

Your hex code:    36 30 30 30 30 34 7C 5D 49 0B EA F7 93 BA 89 D2 C6 C2 41 2A D7 1C 49 8C 6D 4B 5C 07 5A CA 7A 6A C6 D5 D0 6C F7 20 76 5B E0 18 46 93 7E 2A 30 <0D> 14 3A 1A E5 66 7C 05 F9 DF 96 8A F1 45 A5 4A 6E 2F 89 3F F0 93 1F BC 3E 77 5B 27 0C 58 DF 55 37 4C AE 8A E7 C3 C6 16 5B 57 DB 7C 2D 2C 8B 1C E3 A4 44 1B C4 BA 6A C6 98 93 AE 2D 20 6E 9F E8 0F <EB BC 9F 2E 8A E7 CF DA 22 96 E1 74 DE B2 F0 29 EC B1 C1 75 43 1F B2 E5> 1F A5 F6 06 3E 97 A1 A1 93 F4 51 4A C4 14 9F 1A C2 5B BA 02 45 44 2B B3 C2 5B BA 02 45 44 2B B3 C2 5B BA 02 45 44 2B B3 C2 5B BA 02 45 44 2B B3 C2 5B BA 02 45 44 2B B3 C2 5B BA 02 45 44 2B B3 06 0B 12 75 85 8B 07 FB
NeoReader string: 36 30 30 30 30 34 7C 5D 49 0B EA F7 93 BA 89 D2 C6 C2 41 2A D7 1C 49 8C 6D 4B 5C 07 5A CA 7A 6A C6 D5 D0 6C F7 20 76 5B E0 18 46 93 7E 2A 30 <0A> 14 3A 1A E5 66 7C 05 F9 DF 96 8A F1 45 A5 4A 6E 2F 89 3F F0 93 1F BC 3E 77 5B 27 0C 58 DF 55 37 4C AE 8A E7 C3 C6 16 5B 57 DB 7C 2D 2C 8B 1C E3 A4 44 1B C4 BA 6A C6 98 93 AE 2D 20 6E 9F E8 0F <81 50 D0 6B 5E A1 B1 78 4F 53 35 B7 D3 FE 1F DF E1 90 D7 44 A2 5C 00 19> 1F A5 F6 06 3E 97 A1 A1 93 F4 51 4A C4 14 9F 1A C2 5B BA 02 45 44 2B B3 C2 5B BA 02 45 44 2B B3 C2 5B BA 02 45 44 2B B3 C2 5B BA 02 45 44 2B B3 C2 5B BA 02 45 44 2B B3 C2 5B BA 02 45 44 2B B3 06 0B 12 75 85 8B 07 FB

差异解释

事实证明,条形码实际上与您的十六进制代码不匹配。我们的两个代码在 0F 字节处出现分歧,条形码实际上遵循 NeoReader 的建议。如下图所示,放大了条形码的右下象限(蓝线表示未编码数据的部分,它们用于帮助定位扫描仪)。

this video tutorial. Your barcode, however, does not use the string encoding method shown there, as it uses a binary shift escape 的帮助下,我设法手动5 解码了那部分条码以处理 8 位值。从那里我相信一个 0A <-> 0D 差异是由于我的复制粘贴错误造成的。

不幸的是,由于打印机对您来说是一个黑盒子,您似乎无法自行解决此问题。

脚注

  1. 我找不到 Aztec 代码规范,但行为似乎与默认行为相对一致。

  2. ISO-8859-1 本质上是 ASCII 的超集,但它技术上 未定义 ASCII 控制代码范围。这在实践中通常被忽略。

  3. 唯一的区别是我有的斜体0A字符,这是换行符。您的字符串有 0D,另一个换行符。不同的系统以不同的方式处理新行,并且它们自动更改新行字符的情况并不少见。与大多数其他 ASCII 控制代码不同,换行符通常得到很好的支持。

  4. 这个原因很复杂。掩饰一些细节,我相信在点击转换按钮后,它首先被转换为 UTF-16(Javascript 的本机字符串编码)。 ASCII/ISO-8859-1 字符的字节值在 UTF-16 中是相同的。但是,UTF-16 是 16 位编码而不是 8 位编码,因此,额外的 00.

  5. 那是痛苦的。

首先,我尝试了以下在线条码reader:

这让我觉得您的条形码可能构造得不太好...

这是你的输出:

600004|]Iê÷ºÒÆÂA*×ImK\ZÊzjÆÕÐl÷ v[àF~*0
:åf|ùßñE¥Jn/?ð¼>w['XßU7L®çÃÆ[WÛ|-,ã¤DĺjÆ®- nèPÐk^¡±xOS5·Óþßá×D¢\

这是来自 zxing 的:

600004|]I�ê÷ºÒÆÂA*×�ImK\�ZÊzjÆÕÐl÷ v[à�F~*0
�:�åf|�ùßñE¥Jn/?ð�¼>w['�XßU7L®çÃÆ�[WÛ|-,�ã¤D�ĺjÆ®- nè�PÐk^¡±xOS5·Óþ�ßá×D¢\���¥ö�>¡¡ôQJÄ��Â[º�ED+³Â[º�ED+³Â[º�ED+³Â[º�ED+³Â[º�ED+³Â[º�ED+³���u�û

可能 这种差异是由于您这边的 copy/paste 操纵造成的)


这是我能够找到的匹配项:

6  0  0  0  0  4  |  ]  I   �  ê  ÷     º     Ò  Æ  Â 
36 30 30 30 30 34 7c 5d 49  0b ea f7 93 ba 89 d2 c6 c2

A  *  ×  �  I     m  K  \  �  Z  Ê  z  j  Æ  Õ  Ð  l 
41 2a d7 1c 49 8c 6d 4b 5c 07 5a ca 7a 6a c6 d5 d0 6c

÷  v  [  à  �  F     ~  *  0  �     :  �  å  f     | 
f7 20 76 5b e0 18 46 93 7e 2a 30 0d 14 3a 1a e5 66 7c

�  ù  ß        ñ  E  ¥  J  n  /     ?  ð     �  ¼  > 
05 f9 df 96 8a f1 45 a5 4a 6e 2f 89 3f f0 93 1f bc 3e

w  [  '  �  X  ß  U  7  L   ®     ç  Ã  Æ  �  [  W  Û  
77 5b 27 0c 58 df 55 37 4c  ae 8a e7 c3 c6 16 5b 57 db 

|  -  ,  �     ã  ¤  D  �  Ä  º  j  Æ        ®  -     
7c 2d 2c 8b 1c e3 a4 44 1b c4 ba 6a c6 98 93 ae 2d 20 

n     è  �  P 
6e 9f e8 0f eb

而且这个似乎是某种Unicode UCS-2编码。

在此之后,我无法解释输出和预期的十六进制值之间的差异