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();
它们只是表示 Unicode 字符的不同方案。
两者都是可变长度-UTF-16在包含大多数常用字符的基本多语言平面(BMP)中对所有字符使用2字节。
UTF-8对 BMP 中的字符使用1到3个字节,对于当前 Unicode 范围 U + 0000到 U + 1 FFFFFFF 中的字符使用最多4个字节,如果有必要的话,可以扩展到 U + 7 FFFFFFF... ... 但值得注意的是,所有 ASCII 字符都用一个字节来表示。
对于消息摘要来说,选择哪个并不重要,只要尝试重新创建摘要的每个人都使用相同的选项。
有关 UTF-8和 Unicode 的更多信息,请参见 这一页。
(注意,所有 Java 字符都是 BMP 中的 UTF-16代码点; 要表示 U + FFFF 之上的字符,需要在 Java 中使用代理对。)
我相信在网络上有很多关于这方面的好文章,但是这里有一个简短的总结。
UTF-8和 UTF-16都是可变长度编码。然而,在 UTF-8中,一个字符可能至少占用8位,而在 UTF-16中,字符长度从16位开始。
UTF-8的主要优点:
UTF-8的主要缺点:
UTF-16的主要优点:
char
主要 UTF-16缺点:
一般来说,UTF-16通常更适合于内存表示,因为 BE/LE 在那里是不相关的(只需使用本机顺序) ,而且索引更快(只是不要忘记正确处理代理对)。另一方面,UTF-8对于文本文件和网络协议非常有用,因为没有 BE/LE 问题,空终止通常很方便,而且具有 ASCII 兼容性。
这与 UTF-8/16无关(一般来说,尽管它确实可以转换为 UTF16,BE/LE 部分可以设置为 w/a 单行) ,但下面是将 String 转换为 byte []的最快方法。例如: 非常适合所提供的案例(哈希代码)。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 编号之外,每个字符都是它们自己的格式。
UTF-8试图表示,每个 Unicode 数字给予一个字节的字符(如果是 ASCII) ,其他2个字节,其他4个字节等等..。
UTF-16尝试表示,每个 Unicode 数字给出的字符以两个字节开始。如果两个字节不够,那么使用4个字节。如果这也不够,那么使用6字节。
从理论上讲,UTF-16的空间效率更高,但实际上 UTF-8的空间效率更高,因为处理的大多数字符(98% 的数据)是 ASCII,UTF-8尝试用单字节表示它们,而 UTF-16尝试用2字节表示它们。
而且,UTF-8是 ASCII 编码的超集。所以每个需要 ASCII 数据的应用程序都会被 UTF-8处理器接受。对 UTF-16来说,情况并非如此。UTF-16无法理解 ASCII,这是采用 UTF-16的一大障碍。
另一点需要注意的是,目前所有的 UNICODE 都可以适用于最大4字节的 UTF-8(考虑到世界上所有的语言)。这与 UTF-16相同,与 UTF-8(https://stackoverflow.com/a/8505038/3343801)相比没有真正节省空间
因此,人们尽可能地使用 UTF-8。
UTF-8和 UTF-16之间的区别? 我们为什么需要这些?
在 UTF-16的实现中,至少有两个安全漏洞。
WHATWG 和 W3C有 现在宣布,只有 UTF-8可以在 Web 上使用。
这里列出的[安全]问题在完全使用 UTF-8时会消失,这是现在所有事情都必须进行编码的众多原因之一。
其他组织也这么说。
因此,尽管 UTF-16可能会继续被 Java 和 Windows 等一些系统内部使用,但是你可能在过去看到的 UTF-16在数据文件、数据交换等方面的极少使用可能会完全消失。