8

我在评论中读到@Esailija 对我的一个问题的回答

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

我还在@AaronDigulla 的回答中读到:

在 Java 中,ISO-8859-1(又名 ISO-Latin1)是 1:1 映射

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

// \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)在哪里指定- 到源的链接,或者 JSL 会很好。它是具有此属性的唯一编码吗?
  3. 它与ISO-8859-1成为默认默认值有关吗?

另请参阅此问题以获取其他字符集的很好的反例。

4

2 回答 2

14

"\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 参考,声称涵盖了每个字节:

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

(强调我的)

于 2013-04-10T13:22:54.760 回答
5

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

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

另一种选择是忽略无效字节,但这也意味着无限不同的字节序列解码为相同的字符串。您可以用字符串中的十六进制编码替换无效字节,例如"0xFF". 无法判断原始字节是否被合法解码,"0xFF"因此这也不起作用。

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

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

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

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

对于任意二进制数据,其中strisnew String(bytes, "ISO-8859-1")bytes is a byte[]


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

于 2013-04-10T23:01:24.523 回答