UTF-8和UTF-16的区别?

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(); 

我相信在networking上有很多关于这方面的优秀文章,但是这里有一个简短的总结。

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

主要的UTF-8优点:

  • 基本的ASCII字符如数字,没有重音的拉丁字符等占用一个与US-ASCII表示相同的字节。 通过这种方式,所有US-ASCIIstring都变成了有效的UTF-8,在很多情况下它提供了不错的向后兼容性。
  • 没有空字节,它允许使用以空字符结尾的string,这也引入了大量的向后兼容性。
  • UTF-8与字节顺序无关,因此您不必担心Big Endian / Little Endian问题。

主UTF-8缺点:

  • 许多常见的字符长度不同,这会减慢编码点的索引,并可能会严重计算编码点数。
  • 即使字节顺序并不重要,但有时UTF-8仍然具有BOM(字节顺序标记),用于通知文本以UTF-8编码,并且即使文本只包含ASCII字符也不兼容ASCII软件。 微软软件(如记事本)特别喜欢把BOM添加到UTF-8。

主要的UTF-16优点:

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

主UTF-16缺点:

  • 在US-ASCIIstring中有很多空字节,这意味着没有以空字符结尾的string和大量浪费的内存。
  • 在许多常见情况下(特别是在美国/欧盟/西里尔字母/以色列/阿拉伯国家/伊朗等国家),使用它作为固定长度编码“通常会起作用”,如果不这样做,通常会导致断开的支持。 这意味着程序员必须注意代理对,并在重要的情况下正确处理它们!
  • 它的长度是可变的,所以对码点进行计数或索引是很昂贵的,尽pipe比UTF-8less。

一般来说,UTF-16通常比内存表示更好,因为BE / LE在那里是不相关的(只是使用本地顺序),索引更快(只是不要忘记正确处理代理对)。 另一方面,UTF-8对于文本文件和networking协议是非常好的,因为不存在BE / LE问题,空终止常常派上用场,而且兼容ASCII。

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

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

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

就消息摘要而言,只要试图重新创build摘要的每个人都使用相同的选项,那么select哪个就不重要了。

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

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

这与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; } 

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

除了共享给定字符的相同的Unicode编号,每一个都是他们自己的格式。