Shift JIS编码中的非法序列0x82 0x51
我手头有字节序列 0x83 89 83 93 83 4F 83 8A 83 62 83 54 81 5B 82 51,需要判断它是纯ASCII还是某种Shift JIS。它来自一张世嘉Mega Drive的镜像,其中游戏描述是按目标市场(日本、欧洲、美国等)来定位的。
Shift JIS验证……
于是我检查字节是否完全符合Shift JIS的模式:
- 从
0x00到0x1F以及0x7F的字节无效。 - 字节
0x80、0xA0以及从0xFD到0xFF在扩展版本中是有效的。 - 从
0x81到0x9F以及从0xE0到0xEF(在扩展版本中从0xF0到0xFC也是)是一个有效的起始字节,但是: - 如果它们是奇数,随后的字节必须在
0x40与0x7E之间,或在0x80与0x9E之间。 - 如果它们是偶数,随后的字节必须在
0x9F与0xFC之间。
…对照输入
前14个字节按照 Shift JIS字节映射 的规定可以正常工作:
0x83是一个奇数起始字节,后面的字节应在0x40与0x9E之间。- 接下来的5 对字节遵循相同模式。
0x81再次是一个奇数起始字节,后面的字节应在0x40与0x9E之间。- 但最后一对违反了编码:
0x82是一个偶数起始字节,因此其后面的字节必须在0x9F与0xFC之间。但事实并非如此。
把前14个字节翻译成 ラングリッサー,这是可以的。
然而
如果我在WinAPI中使用 MultiByteToWideChar( 932, 0, ... ),其中Code Page 932是 Shift JIS的一个扩展(参见 Code Page 932的布局),并提交全部16个字节,我竟然得到的翻译结果是 ラングリッサー2——从文本上下文来看这也是一个有效的文本(国际版本的游戏标题是 Langrisser II)。
问题
为什么按照Shift JIS,字节序列 0x82 51 是无效的?按 CP 932的布局 应该甚至也是无效的。我到底漏看了什么?
解决方案
Windows 932
关于Code Page 932布局的维基百科条目具有误导性。根据Unicode 1998年的映射,序列 0x82 51 是合法的:
# Column #1 is the cp932 code (in hex)
# Column #2 is the Unicode (in hex as 0xXXXX)
# Column #3 is the Unicode name (follows a comment sign, '#')
0x8251 0xFF12 #FULLWIDTH DIGIT TWO
以 0x82 作为字符的首字节时,后面的字节可以是
- 从
0x4F到0x58,或 - 从
0x60到0x79,或 - 从
0x81到0x9A,或 - 从
0x9F到0xF1——按照布局示意图,这个范围应该是唯一有效的。
Shift JIS 0208
然而,即使是 Unicode对 Shift JIS 0208的映射 也将两字节都视为有效:
# Column #1 is the shift-JIS code (in hex)
# Column #2 is the JIS X 0208 code (in hex as 0xXXXX)
# Column #3 is the Unicode (in hex as 0xXXXX)
# Column #4 the Unicode name (follows a comment sign, '#')
0x8251 0x2332 0xFF12 # FULLWIDTH DIGIT TWO
其实我确实应该查阅实际的文献,看看JIS 0208支持的字节组合要比 [Wikipedia条目中的布局示意] 所暗示的多得多。
结论
我的验证显然是错误的,因为它允许的字节组合太少了。我无法核实这张电子游戏镜像是否按1990年代的原样未被修改,或者其元数据是否使用更新的软件编写,但归根结底这也无关紧要,因为该组合在当时甚至就是有效的 [JIS X 0208]。我很确定世嘉的游戏没有使用Windows,因此我不需要把 932 视为我需要预期的编码。