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


Answers:


284

我相信Web上有很多关于此的好文章,但这是一个简短的摘要。

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

UTF-8主要优点:

  • 基本ASCII字符(例如数字,不带重音的拉丁字符等)占据一个字节,该字节与US-ASCII表示形式相同。这样,所有US-ASCII字符串都变为有效的UTF-8,在许多情况下,它都提供了良好的向后兼容性。
  • 没有空字节,允许使用以空终止的字符串,这也引入了很多向后兼容性。
  • UTF-8与字节顺序无关,因此您不必担心Big Endian / Little Endian问题。

UTF-8主要缺点:

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

UTF-16主要优点:

  • BMP(基本多语言平面)字符,包括拉丁语,西里尔字母,大多数中文(中华人民共和国对BMP以外的某些代码点提供了强制性支持),大多数日语可用2个字节表示。这将加快索引和计算代码点计数情况下,文中包含增补字符。
  • 即使文本具有补充字符,它们仍然由成对的16位值表示,这意味着总长度仍可被2整除,并允许使用16位char作为字符串的原始成分。

UTF-16主要缺点:

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

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


3
UTF16上仅缺少BE / LE部分:) UTF-8还有另一个缺点,它可能比UTF16产生更长的输出
bestsss

4
是的,我忘记了BE / LE。不过,这没什么大不了的,特别是对于内存使用而言。仅当涉及到三字节字符时,UTF-8才会生成更长的输出,但这主要是中文和日文。另一方面,如果文本包含很多US-ASCII字符,则它可能会生成较短的输出,因此它是否有缺点取决于特定的情况。
Sergei Tachenov 2011年

我什至没有想到要提到utf-8的直接优点,即较短的长度。关于utf-8的较长输出,可能是“可能”,这是有原因的,但是如果目标远东,则默认编码应为utf-16。至于示例md.update(text.getBytes(“ UTF-8”)); 编码无关紧要,因为散列在两种情况下都是稳定的。
bestsss 2011年

以字符串转换为字节数组的最快方法是类似的东西,贴跌样本
bestsss

您说字符在UTF-8中具有不同的长度,因此会减慢索引和计算长度,但是我怀疑UTF-16中的字符也具有不同的长度,是否应该更快地对UTF-16进行索引和计算长度?
nicky_zs 2014年

19

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

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

UTF-8在BMP中的字符使用1到3个字节,在当前Unicode范围U + 0000到U + 1FFFFF中的字符最多使用4个字节,并且如果有必要的话可以扩展到U + 7FFFFFFF。但值得注意的是,所有ASCII字符均以单个字节表示。

出于消息摘要的目的,选择哪个选项无关紧要,只要尝试重新创建摘要的每个人都使用相同的选项即可。

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

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


5

安全性:仅使用UTF-8

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

UTF-16的实现中至少存在几个安全漏洞。有关详细信息,请参见Wikipedia

WHATWGW3C现正在申报只有UTF-8要在Web上使用。

仅使用UTF-8时,这里概述的[安全]问题就消失了,这是现在成为所有事物强制编码的众多原因之一。

其他团体也这么说。

因此,尽管Java和Windows等某些系统可能会继续在内部使用UTF-16,但您过去在数据文件,数据交换等方面可能很少使用UTF-16,这可能会完全消失。


4

这与UTF-8 / 16无关(通常,尽管它确实可以转换为UTF16并且BE / LE部分可以用单行设置),但是下面是将String转换为byte []的最快方法。例如:完全适合所提供的情况(哈希码)。String.getBytes(enc)相对较慢。

static byte[] toBytes(String s){
        byte[] b=new byte[s.length()*2];
        ByteBuffer.wrap(b).asCharBuffer().put(s);
        return b;
    }

-2

区分UTF-8和UTF-16的简单方法是识别它们之间的共性。

除了为给定字符共享相同的unicode号外,每个字符都是自己的格式。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.