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();
我相信网上有很多关于这方面的好文章,但这里有一个简短的总结。
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。
它们只是表示 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 中使用代理对。)
这与 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 编号外,每个字符都有自己的格式。
UTF-8 尝试用一个字节(如果是 ASCII)来表示给字符的每个 unicode 数字,否则 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。