UTF-8 和 UTF-16 之间的区别?

2022-08-31 07:38:41

UTF-8 和 UTF-16 之间的区别?我们为什么需要这些?

MessageDigest md = MessageDigest.getInstance("SHA-256");
String text = "This is some text";

md.update(text.getBytes("UTF-8")); // Change this to "UTF-16" if needed
byte[] digest = md.digest();

答案 1

我相信网上有很多关于这方面的好文章,但这里有一个简短的总结。

UTF-8 和 UTF-16 都是可变长度编码。但是,在 UTF-8 中,字符可能至少占用 8 位,而在 UTF-16 字符中,字符长度从 16 位开始。

UTF-8 的主要优点:

  • 基本的ASCII字符,如数字,没有重音符号的拉丁字符等,占用一个字节,这与US-ASCII表示相同。通过这种方式,所有 US-ASCII 字符串都成为有效的 UTF-8,这在许多情况下提供了不错的向后兼容性。
  • 没有空字节,允许使用空终止的字符串,这也引入了大量的向后兼容性。
  • UTF-8 独立于字节顺序,因此您不必担心大字节序/小字节序问题。

UTF-8 的主要缺点:

  • 许多常见字符具有不同的长度,这大大减慢了代码点索引和计算代码点计数的速度。
  • 尽管字节顺序无关紧要,但有时 UTF-8 仍然具有 BOM(字节顺序标记),用于通知文本以 UTF-8 编码,并且即使文本仅包含 ASCII 字符,也会破坏与 ASCII 软件的兼容性。微软软件(如记事本)特别喜欢将BOM添加到UTF-8中。

UTF-16 的主要优点:

  • BMP(基本多语言平面)字符,包括拉丁语、西里尔文、大多数中文(PRC强制支持 BMP 以外的某些码位),大多数日语可以用 2 个字节表示。这可以加快索引和计算代码点计数的速度,以防文本不包含增补字符。
  • 即使文本具有增补字符,它们仍由 16 位值对表示,这意味着总长度仍可被 2 整除,并允许使用 16 位作为字符串的基本组件。char

UTF-16 的主要缺点:

  • US-ASCII 字符串中有很多空字节,这意味着没有空终止的字符串和大量浪费的内存。
  • 在许多常见情况下,将其用作固定长度的编码“大多有效”(特别是在美国/欧盟/西里尔字母的国家/以色列/阿拉伯国家/伊朗和许多其他国家/地区),通常会导致支持中断。这意味着程序员必须了解代理项对,并在重要的情况下正确处理它们!
  • 它的长度是可变的,因此计算或索引代码点的成本很高,尽管小于 UTF-8。

通常,UTF-16 通常更适合内存中的表示,因为 BE/LE 在那里无关紧要(只是使用本机顺序)并且索引更快(只是不要忘记正确处理代理项对)。另一方面,UTF-8对于文本文件和网络协议非常好,因为没有BE / LE问题,空终止通常派上用场,以及ASCII兼容性。


答案 2

它们只是表示 Unicode 字符的不同方案。

两者都是可变长度的 - UTF-16 对基本多语言平面 (BMP) 中的所有字符使用 2 个字节,其中包含最常用的大多数字符。

UTF-8 对 BMP 中的字符使用 1 到 3 个字节,对于当前 Unicode 范围 U+0000 到 U+1FFFFF 中的字符,最多使用 4 个字节,如果需要,可以扩展到 U+7FFFFFFFFF...但值得注意的是,所有 ASCII 字符都以单个字节表示。

出于消息摘要的目的,选择其中哪一个并不重要,只要尝试重新创建摘要的每个人都使用相同的选项即可。

有关 UTF-8 和 Unicode 的更多信息,请参阅此页面

(请注意,所有 Java 字符都是 BMP 中的 UTF-16 码位;要表示 U+FFFF 以上的字符,您需要在 Java 中使用代理项对。


推荐