【问题标题】:java utf8 encoding - char, string typesjava utf8 编码 - 字符、字符串类型
【发布时间】:2012-08-24 15:16:37
【问题描述】:
public class UTF8 {
    public static void main(String[] args){
        String s = "ヨ"; //0xFF6E
        System.out.println(s.getBytes().length);//length of the string
        System.out.println(s.charAt(0));//first character in the string
    }
}

输出:

3
ヨ

请帮助我理解这一点。试图了解 utf8 编码在 java 中是如何工作的。 根据 char 的 java doc 定义 char:char 数据类型是单个 16 位 Unicode 字符。

是不是说java中的char类型只能支持那些可以用2个字节表示的unicode字符,不超过那个?

在上面的程序中,为该字符串分配的字节数为 3,但在返回第一个字符(java 中为 2 个字节)的第三行中可以容纳一个 3 个字节长的字符? 真的很困惑吗?

任何关于 java/general 中这个概念的好的参考都将非常感激。

【问题讨论】:

标签: java utf-8


【解决方案1】:

您的代码示例中没有任何内容直接使用 UTF-8。 Java 字符串在内存中使用 UTF-16 进行编码。不适合单个 16 位字符的 Unicode 代码点将使用称为代理对的 2 字符对进行编码。

如果您不将参数值传递给String.getBytes(),它会返回一个字节数组,其中包含使用底层操作系统默认字符集编码的String 内容。如果要确保 UTF-8 编码的数组,则需要改用 getBytes("UTF-8")

调用 String.charAt() 仅从字符串的内存存储中返回一个原始的 UTF-16 编码字符。

因此,在您的示例中,Unicode 字符 使用 UTF-16 编码的两个字节(0x6E 0xFF0xFF 0x6E 取决于字节序)存储在内存中的 String 存储中,但存储在在来自getBytes() 的字节数组中使用三个字节,这些字节使用操作系统默认字符集进行编码。

在 UTF-8 中,该特定 Unicode 字符恰好也使用 3 个字节 (0xEF 0xBD 0xAE)。

【讨论】:

  • 我猜他的系统默认编码是UTF-8
【解决方案2】:

String.getBytes() 使用不需要匹配内部表示的平台默认字符编码返回字节。

在大多数情况下,最好不要使用此方法,因为在大多数情况下,依赖平台的默认编码是没有意义的。请改用String.getBytes(String charsetName),并明确指定用于将字符串编码为字节的字符集。

【讨论】:

    【解决方案3】:

    UTF-8 是一种可变长度编码,ASCII 字符仅使用一个字节(0 到 127 之间的值),其他 unicode 符号使用两个、三个(甚至更多)字节。

    这是因为字节的高位用来告诉“这是一个多字节序列”,所以 8 上的一位并不是用来实际表示“真实”数据(char 码)而是用来标记字节.

    因此,尽管 Java 在 ram 中为每个字符使用 2 个字节,但当使用 UTF-8 “序列化”字符时,它们可能会在结果字节数组中产生一个、两个或三个字节,这就是 UTF-8 编码的工作原理.

    【讨论】:

    • UTF-8 最多使用 2 个字节
    • UTF-8 最多使用 4 个字节,而不是 2 个字节(如果您考虑在 UTF-8 被修改为不超过 UTF-16 支持的代码点之前的旧 UTF-8 规范,则为 6 个字节)。
    • @adosaiguas “UTF-8 使用 1 到 4 个 8 位字节对 Unicode 字符集中的 1,112,064[7] 个代码点进行编码”(维基百科)
    • @RemyLebeau 你们说的都对,对不起,我一直认为它是 UTF-8 最大 2 个字节和 UTF-16 最大 4 个字节。
    • 关于第三个陈述的问题。 “尽管 Java 为每个字符在 ram 中使用 2 个字节”。这是否意味着 java 使用 16 位来表示 unicode 的 1,112,064 个代码点? (2 power 16) 不小于代码点数吗?这是一个有效的问题吗?
    【解决方案4】:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 2012-08-20
      相关资源
      最近更新 更多