3

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

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);

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

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

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

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

Charset.forName("Shift_JIS").newEncoder().replacement()
  • 那么为什么在 Shift-JIS 中没有映射单一宽度日元?
  • [-4, -4] 是一个明智的编码器替代品吗?
  • 为什么解码器不支持 0x5C 映射到日元 (U+00A5)?
  • 如果 0x5C 不是正确的编码,那是什么?
4

1 回答 1

4

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

C:¥Documents¥something.doc

)。因此,字节在某种意义上是日元符号,但在某种意义上也是反斜杠;根据http://archives.miloush.net/michkap/archive/2005/09/17/469941.html,在日文系统上,根据字体的不同,相同的字节甚至被渲染为这些符号中的不同之一。

编码中符号缺乏一致的含义意味着虽然 Shift-JIS编码器\可以将和都映射¥到 byte 0x5C,但尝试将 Shift-JIS 编码的字符串映射到 unicode 代码点序列的解码器没有知道是将字节转换0x5C为反斜杠还是日元符号的方法;日本用户过去常常通过他们的字体选择来做出选择(如果他们能够做到的话)。

面对这种无法解决的歧义,所有解码器似乎都选择解码0x5C为反斜杠。(至少,Python 做到了这一点,而且WhatWG 有一个规范来规定它。)

至于当被要求对日元登录进行编码时,Java/Android 特别是在做什么的细节,shift_jis恐怕我不知道。

于 2017-01-07T16:44:41.650 回答