将二进制数据存储在QR码中

Tim*_*mmm 5 qr-code zxing

我正在尝试将二维数据存储在QR码中。显然,QR码确实支持存储原始二进制数据(或ISO-8859-1 / Latin1)。这是我要编码(十六进制)的内容:

d1 50 01 00 00 00 f6 5f 05 2d 8f 0b 40 e2 01
Run Code Online (Sandbox Code Playgroud)

我尝试了以下编码器:

  1. qr.js

qrjs

  1. Google图表

图表

  1. qrcode.js

qrcode.js

zxing.org解码会产生各种不正确的结果。这两个javascript会产生此错误(这是错误的;第一个文本字符应为Ñ。

qr.js和qrcode.js

而Google图表会生成此...

画什么

到底是怎么回事?这些正确吗?真正奇怪的是,如果我编码此序列(至少使用JS序列),那么它可以正常工作-我本来以为问题是非ASCII字符,但Ñ(0xd1)是非ASCII。

d1 50 01 00 00 00 01 02 03 04 05 06 40 e2 01
Run Code Online (Sandbox Code Playgroud)

有人知道发生了什么吗?

更新资料

我想到用我发现的基于ZBar的扫描仪应用程序扫描它们。它可以正常扫描两个JS版本(至少它们以ÑP开头)。Google Charts只是一个错误。因此,似乎ZXing出现了问题(令人惊讶的是,我不会推荐给任何人)。

更新2

ZBar无法处理空字节。:-(

小智 7

“这是怎么回事?这些正确吗?”

除了谷歌图表(只是空的),你的二维码是正确的。

您可以看到来自 zxing 的二进制数据是您所期望的:

4: Byte mode indicator  
0f: length of 15 byte  
d15001...: your 15 bytes of data  
ec11 is just padding  
Run Code Online (Sandbox Code Playgroud)

问题来自解码。因为大多数解码器会尝试将其解释为文本。但由于它是二进制数据,您不应该尝试将其作为文本处理。即使您认为可以将其从文本转换为二进制,正如您所见,这可能会导致无效文本值出现问题。

所以解决方案是使用一个解码器来输出二进制数据,而不是文本数据。

现在关于将二维码二进制数据解释为文本,你说第一个字符应该是 'Ñ' 如果将其解释为“ISO-8859-1”,这是正确的,根据二维码标准,这是应该做的没有定义 ECI 模式。

但实际上,在这种情况下,大多数智能手机二维码阅读器会将其解释为 UTF-8(或至少尝试自动检测编码)。

尽管这不是标准,但这已成为普遍做法:没有 ECI、UTF-8 编码文本的二进制模式。

也许背后的原因是没有人愿意浪费这些宝贵的字节添加指定 UTF-8 的 ECI 模式。实际上,并非所有解码器都支持 ECI。


Max*_*tin 6

要将二进制数据存储在二维码中,您必须克服两个问题。

  1. ISO-8859-1 不允许 00-1F 和 7F-9F 范围内的字节。如果您无论如何都需要对这些字节进行编码,请引用或编码它们,即使用带引号的可打印或 Base-64 编码来避免这些范围。

  2. 由于您尝试将二进制数据存储在二维码中,因此您只能依靠自己的扫描仪来处理这些二进制数据。您不必通过其他软件(例如 zxing.org 上的 Web 应用程序)显示 QR 码中的文本,因为大多数 QR 解码器(包括 zxing.org 的解码器)使用启发式方法来检测使用的字符集。这些启发式方法可能会检测到 ISO-8859-1 以外的字符集,因此无法正确显示您的二进制数据。一些扫描器使用启发式方法来检测字符集,即使字符集是由 ECI 明确给出的。这就是为什么提供 ECI 可能没有多大帮助——即使使用 ECI,扫描仪仍然使用启发式方法。

因此,仅使用 US-ASCII 可打印字符(例如,在将二进制数据传递给 QR 码生成器之前以 Base64 编码的二进制数据)是对抗试探法的 QR 码的最安全选择。这还将克服另一个复杂问题:ISO-8859-1 不是 2000 年发布的早期二维码标准 (ISO/IEC 18004:2000) 中的默认编码。该标准确实指定了符合 JIS X 0201(JIS8 也称为 ISO-2022-JP)的 8 位拉丁文/假名字符集作为 8 位模式的默认编码,而 2005 年发布的更新标准确实将默认值更改为ISO-8859-1。

作为 Base-64 的替代方案,您可以使用两个十六进制字符(0-9,AF)对每个字节进行编码,因此,在 QR 码中,您的数据将以字母数字模式而非 8 位模式进行编码。这肯定会禁用所有启发式方法,并且不应产生比 Base-64 更大的二维码,因为字母数字模式中的每个字符在二维码流中仅占 6 位。

  • 如果您查看代码页布局中的字符映射表 https://en.wikipedia.org/wiki/ISO/IEC_8859-1#Code_page_layout 您将看到值 00-1F 和 7F-9F 是“未定义”,即不编码任何定义的字符。ISO 8859-1 对其所谓的“拉丁字母表 1”进行编码,由拉丁字母中的 191 个字符组成。 (2认同)

Tim*_*mmm 2

事实证明,ZXing 只是垃圾,而 ZBar 对数据做了一些奇怪的事情(例如将其转换为 UTF-8)。我设法让它输出包括空字节的原始数据。这是我发现的最好的 Android ZBar 库的补丁,现已合并。