ISO-8859-1编码和二进制数据保存

时间:2013-04-10 12:11:28

标签: java character-encoding iso-8859-1

我在comment读到了@Esailija对我的一个问题的回答

  

ISO-8859-1是唯一完全保留原始二进制数据的编码,精确字节< - >代码点匹配

我也在@AaronDigulla的answer中读到:

  

在Java中,ISO-8859-1(a.k.a ISO-Latin1)是1:1的映射

我需要对此有所了解。这将失败(如图here所示):

// \u00F6 is ö
System.out.println(Arrays.toString("\u00F6".getBytes("utf-8")));
// prints [-61, -74]
System.out.println(Arrays.toString("\u00F6".getBytes("ISO-8859-1")));
// prints [-10]

问题

  1. 我承认我不太明白 - 为什么它没有得到上面代码中的字节
  2. 最重要的是, 这是 ISO-8859-1字节保留行为) 指定的 em> - 链接到源,或者JSL会很好。它是唯一具有此属性的编码吗?
  3. 是否与ISO-8859-1成为default default
  4. 有关

    另请参阅this question以获取其他字符集的精彩计数器示例。

2 个答案:

答案 0 :(得分:12)

"\u00F6"不是字节数组。它是一个包含单个字符的字符串。改为执行以下测试:

public static void main(String[] args) throws Exception {
    byte[] b = new byte[] {(byte) 0x00, (byte) 0xf6};
    String s = new String(b, "ISO-8859-1"); // decoding
    byte[] b2 = s.getBytes("ISO-8859-1"); // encoding
    System.out.println("Are the bytes equal : " + Arrays.equals(b, b2)); // true
}

要检查任何字节是否为真,只需通过所有字节改进代码:

public static void main(String[] args) throws Exception {
    byte[] b = new byte[256];
    for (int i = 0; i < b.length; i++) {
        b[i] = (byte) i;
    }
    String s = new String(b, "ISO-8859-1");
    byte[] b2 = s.getBytes("ISO-8859-1");
    System.out.println("Are the bytes equal : " + Arrays.equals(b, b2));
}

ISO-8859-1是标准编码。所以使用的语言(Java,C#或其他)并不重要。

这是一个Wikipedia reference声称每个字节都被覆盖:

  

1992年,IANA注册了字符映射ISO_8859-1:1987,更常见的是其首选的MIME名称ISO-8859-1(请注意ISO 8859-1的额外连字符),ISO 8859的超集 - 1,用于互联网。此映射将C0和C1控制字符分配给未分配的代码值,从而通过每个可能的8位值提供256个字符。

(强调我的)

答案 1 :(得分:4)

对于保留原始二进制数据的编码,需要将每个唯一字节序列映射到唯一字符序列。

这排除了所有多字节编码(UTF-8/16/32,Shift-Jis,Big5等),因为并非每个字节序列都有效 因此会解码为一些替换字符(通常是?或 )。没有办法从字符串中分辨出什么原因 解码后的替换字符。

另一个选择是忽略无效字节但这也意味着无限不同 字节序列解码为相同的字符串。您可以使用十六进制编码替换无效字节 在像"0xFF"这样的字符串中。没有办法判断原始字节是否合法解码 到"0xFF"所以这也不起作用。

这留下了8位编码,其中每个序列只是一个字节。单字节有效 如果有它的映射。但是许多8位编码都有漏洞,不能编码256个不同的字符。

要保留原始二进制数据,您需要编码256个不同字符的8位编码。 ISO-8859-1 在这方面不是独一无二的。但它的独特之处在于,解码后的代码点的值也是字节的值 它是从。解码的。

所以你有解码后的字符串和编码字节,那么它总是

(byte)str.charAt(i) == bytes[i] 

表示strnew String(bytes, "ISO-8859-1")bytes的任意二进制数据 是byte[]


它也与Java无关。我不知道他的评论意味着什么,这些是字符编码的属性,而不是编程语言。