为什么日元(U + 00A5)符号的Android Shift-JIS编码产生-4,-4?

时间:2015-11-16 00:34:51

标签: android character-encoding shift-jis

运行以下代码似乎生成了错误的值:

byte[] data = "\u00a5".getBytes("Shift_JIS");

它产生[-4,-4],但我期望[0x5c]

我尝试过各种替代名称,“Shift-JIS”,“shift_jis”,“cp932”等都会产生相同的结果。

当我将结果数据输入Shift-JIS解码器时,我得到一个例外:java.nio.charset.UnmappableCharacterException: Length: 2

即,解码器配置如下:

Charset charset = Charset.forName("Shift_JIS);
        CharsetDecoder decoder = charset.newDecoder()
                .onMalformedInput(CodingErrorAction.REPORT)
                .onUnmappableCharacter(CodingErrorAction.REPORT);

但鉴于编码器的输出看起来不对,我的猜测是解码器无关紧要。我的观点是,无论实际字节如何,编码器都会生成无法解码的数据。

全宽Yen(U + FFE5)编码为[-127(0x81), - 113(0x8F)],并正确解码。

奇怪的是,如果我尝试解码[92(0x5C)]这就是我认为单宽度Yen的Shift-JIS编码,则Android / Java解码器产生反斜杠,将字符保留为92. / p>

如果编码器不支持给定的字符,我会期待一个替换字符,例如'?'。但-4(0xFC)似乎甚至不是有效的Shift-JIS。它甚至不是Unicode替换字符U + FFFD。 使用以下行我可以看到编码器似乎配置为使用[-4,-4]:

Charset.forName("Shift_JIS").newEncoder().replacement()
  • 那么为什么不在Shift-JIS中映射单宽度Yen?
  • [-4,-4]是一种合理的编码器更换吗?
  • 为什么解码器不支持0x5C映射到Yen(U + 00A5)?
  • 如果0x5C不是正确的编码,那是什么?

1 个答案:

答案 0 :(得分:2)

部分答案:当微软为Windows创建其东亚代码页时,如日语代码页932和韩语949,他们将字节0x5C渲染为货币符号(日元符号或在文件路径中仍然在语法上充当反斜杠字符(因此日语系统上的文件路径可能看起来像

C:¥Documents¥something.doc

)。因此字节在某种意义上是一个日元符号,但在某种意义上也是反斜杠;根据{{​​3}},在日语系统上,相同的字节甚至被渲染为这些符号中的不同的一个,具体取决于 font

编码中缺少符号的一致含义意味着虽然Shift-JIS 编码器可以合理地将\¥映射到字节{{ 1}},解码器尝试将Shift-JIS编码的字符串映射到unicode代码点序列无法知道是否将字节0x5C转换为反斜杠或者日元符号;日本用户过去通过他们的 font 选择做出这个选择(如果他们能够做到的话)。

面对这种无法解决的歧义,所有解码器似乎都选择将0x5C解码为反斜杠。 (至少,Python会这样做,http://archives.miloush.net/michkap/archive/2005/09/17/469941.html。)

至于要求在0x5C编码日元符号时,特别是Java / Android正在做什么的细节,我恐怕不知道。