问题在于,大多数扫描仪似乎仍然使用JIS8(QR 2000)而不是iso-8859(QR 2005)作为默认值,因此使用iso-8859进行编码通常不起作用。
似乎utf-8是唯一的选择,即使它违反了规范。
编辑:我将使用没有ECI和BOM的utf-8。虽然违反了所有规范和精神,但目前效果最好。
我的经验表明,零宽不断空格(BOM)无济于事。如果QR扫描仪无法从正确编码的UTF-8字符串(数据流中的8位字节模式)中显示一个字符串,即使使用ECI添加BOM也没有任何区别。
以无法正确显示UTF-8字符的扫描仪为例,拿小米手机MIUI Global v11.0.3(带有其本机扫描器应用程序)为例。即使在ECI中指定了该字符集,这些手机也无法正确显示以UTF-8编码的西里尔文字符串。西里尔字符会显示为问号。但是,如果在西里尔文本中添加一个中文/日文字符(例如“日”),小米就可以正确显示整个文本,而这与BOM无关。
您认为在QR码中使用UTF-8而不是ISO-8859-1更好,因为ISO-8859-1不是2000年发布的早期QR码标准(ISO/IEC 18004:2000)的默认编码。该标准按照JIS X 0201(JIS8,也称为ISO-2022-JP)规定了8位拉丁文/假名字符集作为8位模式的默认编码,而在2005年发布的更新标准中将默认编码更改为ISO-8859-1。因此,您认为“使用iso-8859进行编码通常不起作用”。
这取决于您是否只需要US-ASCII字符(具体来说,20
-7E
范围内的可打印ANSI X3.4-1986字符),而且您不需要在加泰罗尼亚语、法语、加利西亚语、德语、奥克语和西班牙语等语言中使用umlaut/diaeresis的ISO-8859-1字符。
如果您只需要US-ASCII,则使用ISO-8859-1而不需要ECI是安全的,而不是使用带有ECI的UTF-8。无论如何,20
-7E
范围内的US-ASCII字符的八位字节字符串无论是编码为ISO-8859-1还是UTF-8都是相同的。扫描仪使用的启发式软件应该能够自动确定所使用的字符集,如果您只使用US-ASCII字符,则可以自动找到它们。如果需要umlaut/diaeresis字符,则使用UTF-8。这不是因为QR码标准在2000年和2005年修订版之间默认编码从JIS X 0201更改为ISO-8859-1,而是因为QR扫描仪使用启发式来自动检测编码,在某些情况下,这个启发式会失败。
众所周知,QR码有四种文本存储模式:(1) 数字模式,(2) 字母数字模式,(3) 8位字节模式,以及(4) 汉字模式。
因此,QR码标准并不支持UTF-8编码。要在8位字符串中使用UTF-8编码(而不是默认的“ISO-8859-1”或“JIS8”),实现必须在该字符串之前插入一个扩展通道解释(ECI)。ECI是QR码的可选附加功能,但至少在2000年时最早定义在QR码标准中。ECI使得可以使用字符集以外的数据编码方式。它还使得可以对其他行业特定要求进行编码,例如使用定义的压缩方案压缩的紧缩数据或其他数据解释。
ECI协议在由AIM公司开发的规范中定义,需要购买,价格为50美元,网址为https://www.aimglobal.org/technical-symbology.html
不幸的是,并非所有的QR码扫描器都能处理ECI协议,即使只是将默认编码更改为UTF-8这样的基本事项也不行。大多数实现使用启发式算法,即字符编码检测算法之一来猜测编码,即使在解码的QR码的ECI中明确指定了编码。他们使用启发式算法不仅是因为2000年至2005年间默认编码从JIS8变为ISO-8859-1导致的。主要原因是缺乏适当的ECI协议支持,可能是由于QR码规范和AIM ECI协议规范是不同的文档。一些QR编码器不通过ECI指定字符编码,而是使用不同的编码方式对8位字符串进行编码(如JIS8、Shift_JIS、ISO-8859-1、UTF-8),因此扫描仪需要应对这种情况。
您曾写道,“似乎只有utf-8是唯一的选择”,但扫描仪使用的启发式算法可能会连UTF-8都失败,就像我给出的小米例子一样。您还写道,UTF-8“违反了规范”,但只有当没有通过ECI显式地指定UTF-8编码时才是这样。
顺便提一下,使用ECI并不是唯一的选择。您可以使用umlaut / diaeresis编码拉丁字符,或使用“Kanji”模式编码Cyrillic字符。在这种模式下,“Shift_JIS”用于编码JIS X 0208字符的范围为8140
-9FFC
和E040
-EBBF
。 在此模式下,您不能通过字节代码20对其他范围中的字符进行编码,但是您可以将其编码为JIS X 0208行1列21(即2121)。由于JIS X 0208具有罗马字母(第3行),希腊字母(第6行)和西里尔字母(第7行)以及特殊字符(第1和2行)的行,因此您可以在JIS字符范围8140
-9FFC
和E040
-EBBF
内完全使用JIS X 0208编码包括umlaut / diaeresis拉丁字符或Cyrillic文本(包括空格和标点符号)。在这种情况下,不需要使用ECI扩展。但是,并不能保证扫描软件中的启发式算法不会破坏您正确编码的文本。
使用UTF-8并通过ECI指定它不是完全的解决方案(因为一些扫描仪在这种情况下仍将使用容易出错的启发式算法),但至少可以帮助符合标准的扫描仪,不像BOM根本没有帮助。