为什么一个中文字符占用一个字符(2个字节)但是需要3个字节的空间?

6
我有以下程序来测试Java如何处理中文字符:

我有以下程序来测试Java如何处理中文字符:

String s3 = "世界您好";
char[] chs = s3.toCharArray();
byte[] bs = s3.getBytes(StandardCharsets.UTF_8);
byte[] bs2 = new String(chs).getBytes(StandardCharsets.UTF_8);

System.out.println("encoding=" + Charset.defaultCharset().name() + ", " + s3 + " char[].length=" + chs.length
                + ", byte[].length=" + bs.length + ", byte[]2.length=" + bs2.length);

打印输出结果如下:

encoding=UTF-8, 世界您好 char[].length=4, byte[].length=12, byte[]2.length=12

结果如下:
  1. 如果使用char[]来保存中文字符,则一个中文字符需要占用1个char,即Java中的2个字节;

  2. 如果使用byte[]来保存中文字符,则一个中文字符需要占用3个byte

我的问题是,如果两个字节足够了,为什么我们要使用三个字节?如果两个字节不够用,为什么我们要使用两个字节?
编辑:
我的JVM默认编码设置为UTF-8。

你正在使用不同的编码方式。你不能只是取这些字符的字节。 - Sami Kuhmonen
1
UTF-8编码可以使用每个字符最多4个字节。请参见https://en.wikipedia.org/wiki/UTF-8。 - Michael Markidis
欢迎来到奇妙的文本编码世界。 - Lew Bloch
你为什么认为2个字节就足够了?[U+1F6B2](http://graphemica.com/%F0%9F%9A%B2)占用2个`char`,即4个字节。 - Tom Blodget
1个回答

5
Java的char类型在两个字节对象中存储16位数据,每个位都用于存储数据。但UTF-8不是这样的。对于汉字,UTF-8只使用每个字节的6位来存储数据。其他两位包含控制信息。(这取决于字符。对于ASCII字符,UTF-8使用7位。)这是一种复杂的编码机制,但它允许UTF-8存储长达32位的字符。这具有每个字符仅占用一个字节的优点,适用于7位(ASCII)字符,使其向后兼容ASCII。但它需要3个字节来存储16位的数据。您可以通过在维基百科上查找了解它的工作原理。

它在UTF-8维基百科文章的“编码”部分中得到了很好的描述,包括特殊字符或语言的示例,https://en.wikipedia.org/wiki/UTF-8#Encoding - MichaelHuelsen
我应该补充一点,UTF-8 的设计也考虑了与 C 和 C++ 的兼容性。在这些语言中,一个零字节值意味着字符串的结束。UTF-8 被设计为永远不会为多字节字符的一个字节产生零字节。 - MiguelMunoz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接