UTF-16与UTF-8兼容吗?

mik*_*ike 1 encoding utf-8 utf-16

我问谷歌上面的问题,并被发送到UTF-8和UTF-16之间的差异?遗憾的是,这个问题没有回答.

根据我的理解,UTF-8应该是UTF-16的一个子集,意思是:如果我的代码使用UTF-16并且我输入UTF-8编码的字符串,那么一切都应该没问题.反过来(期望UTF-8和获得UTF-16)可能会导致问题.

那是对的吗?

编辑:澄清为什么链接的SO问题不回答我的问题:我的问题是在尝试使用时处理JSON字符串时出现的WebClient.DownloadString,因为WebClient使用了错误的编码.我从请求中收到的JSON编码为UTF-8,对我来说问题是:如果我设置webClient.Encoding = New System.Text.UnicodeEncoding(又名UTF-16)我会安全,即能够处理UTF-8和UTF-16请求结果,还是应该使用webClient.Encoding = New System.Text.UTF8Encoding

tri*_*eee 7

目前尚不清楚"兼容"是什么意思,所以让我们先了解一些基础知识.

Unicode是基本概念,正确实现,UTF-16和UTF-8是两种不同的Unicode编码方式.它们显然是不同的 - 否则,为什么会有两个不同的概念?

Unicode本身不指定序列化格式.UTF-8和UTF-16是两种可选的序列化格式.

它们是"兼容的",因为它们可以表示相同的Unicode代码点,但"不兼容",因为表示完全不同.

UTF-16还有两个额外的曲折.实际上有两种不同的编码,UTF-16LE和UTF-16BE.这些在字节序上有所不同.(UTF-8是字节编码,因此没有字节顺序.)旧版UTF-16曾被限制为65,536个可能的字符,这些字符小于当前包含的Unicode.这是由代理人处理的,但是真正旧的和/或破坏的UTF-16实现(正确地标识为UCS-2,而不是"真正的"UTF-16)不支持它们.

对于一点结论,让我们比较四个不同的代码点.我们选择U + 0041,U + 00E5,U + 201CU + 1F4A9,因为它们很好地说明了差异.

U + 0041是一个7位字符,因此UTF-8只用一个字节表示它.U + 00E5是一个8位字符,因此UTF-8需要对其进行编码.U + 1F4A9在基本多语言平面之外,因此UTF-16用代理序列表示它.最后,U + 201C不是上述之一.

以下是UTF-8,UTF-16LE和UTF-16BE中候选字符的表示.

Character | UTF-8               | UTF-16LE            | UTF-16BE            |
----------+---------------------+---------------------+---------------------+
U+0041    | 0x41                | 0x41 0x00           | 0x00 0x41           |
U+00E5    | 0xC3 0xA5           | 0xE5 0x00           | 0x00 0xE5           |
U+201C    | 0xE2 0x80 0x9C      | 0x1C 0x20           | 0x20 0x1C           |
U+1F4A9   | 0xF0 0x9F 0x92 0xA9 | 0x3D 0xD8 0xA9 0xDC | 0xD8 0x3D 0xDC 0xA9 |
Run Code Online (Sandbox Code Playgroud)

为了选择一个明显的例子,如果解释为UTF-16,U + 00E5的UTF-8编码将代表完全不同的字符(在UTF-16LE中,它将是U + A5C3,在UTF-16BE中,U + C3A5. )相反,许多UTF-16代码根本不是有效的UTF-8序列.所以从这个意义上说,UTF-8和UTF-16完全不完全兼容.

在现代编程语言中,您的代码应该只使用Unicode,并让语言处理以适合您的平台和库的方式编码它的细节.有点切线,另见http://utf8everywhere.org/

  • 我非常不同意:很清楚所问的是什么“UTF-8 是 UTF-16 的子集吗?” 答案显然是“不”。 (3认同)