我正在阅读包含“\ ud83e \ udd14”的UTF-8文字。阅读规范,它说没有使用U + D800到U + DFFF。然而,如果我通过解码器(如Microsoft的System.Web.Helpers.Json.Decode)运行它,它会产生一个舌头表情的正确结果。该文本来自Twitter的搜索API。
我的问题:如何解码这个序列?我正在寻找最终的十六进制序列以及它是如何获得的。谢谢你的指导。如果我的问题不明确,请告诉我,我会尽力改进。
答案 0 :(得分:2)
你是从一个有趣的角度来看待这个。首先要注意的是,您要处理两个级别的文本:JSON文档和其中的字符串。
概要:您不需要编写代码来解码它。使用将JSON反序列化为对象的库,例如Newtonsoft' JSON.Net。
但是,首先是Unicode。 Unicode是一个具有一点历史记录的字符集。与几乎每个字符集不同,1)它有多个编码,2)它仍在增长。几十年前,它有+ 65636个码点,这被认为是足够的。因此,使用2字节整数对每个代码点进行编码是计划。它被称为UCS-2,或简称为Unicode编码。 (微软一直坚持使用.NET中的Encoding.Unicode,这会造成一些混乱。)
除此之外:使用U + ABCD(十六进制)格式识别代码点以供讨论。
然后Unicode联盟决定添加更多代码点:一直到U + 10FFFF。为此,编码至少需要21位。 UTF-32,32位整数,是一个明显的解决方案,但不是很密集。因此,使用可变数量的代码单元的编码发明。 UTF-8使用一到四个8位代码单元,具体取决于代码点。
但是很多语言在20世纪90年代都采用了UCS-2。当然,文档可以随意转换,但是处理UCS-2的代码会在没有扩展字符集的兼容编码的情况下中断。由于U + D800到U + DFFF未分配,UCS-2可以保持不变,而那些代理点代码点#34;可用于编码新的代码点。结果是UTF-16。每个码点以一个或两个16位代码单元编码。因此,处理UCS-2的程序可以自动处理UTF-16,只要它们不需要理解它即可。在同一系统中编写的程序可以被认为是处理UTF-16,特别是对于理解它的库。像字符串长度这样的东西仍然存在UTF-16代码单元数量而不是代码点数量的危险,但它还是运行良好。
对于\ ud83e \ udd14表示法,语言在其语法或文字字符串中使用Unicode,希望以非Unicode编码方式接受源文件,并且仍然支持所有Unicode代码点。在20世纪90年代设计时,他们只是用十六进制编写了UCS-2代码单元。当然,这也扩展到UTF-16。这种UTF-16代码单元转义语法允许中间系统使用非Unicode编码处理源代码文件。
现在,JSON基于JavaScript,而JavaScript的字符串是UTF-16代码单元的序列。因此JSON采用了JavaScript中的UTF-16代码单元转义语法。但是,它并不是非常有用(除非您必须处理不能使用UTF-8或处理他们不理解为二进制文件的中间系统)。旧的JSON标准要求在系统之间交换的JSON文档使用UTF-8,UTF-16或UTF-32进行编码。新的[RFC8259]( https://tools.ietf.org/html/rfc8259)需要UTF-8。
因此,您没有" UTF-8文本",您使用UTF-8进行Unicode文本编码。文本本身是一个JSON文档。 JSON文档的名称和值是Unicode文本,作为允许转义的UTF-16代码单元的序列。您的文档的代码点为U + 1F914,而不是""但作为" \ ud83e \ udd14"。
有很多库将JSON转换为对象,因此您不需要解码JSON文档中的名称或值。要手动执行此操作,您将识别转义前缀,并将接下来的4个字符作为代理项的位,extracting the data bits, then combine使用配对代理项中的位来跟随它。
答案 1 :(得分:0)
我以为我会读到UTF-16,看看它是否给了我任何线索,事实证明这就是它所谓的代理对。解码的十六进制公式为:
(H-D800)* 400 +(L-DC00)+ 10000
其中H是第一个(高)代码点,L是第二个(低)代码点。
所以\ ud83e \ udd14变为1f914
显然,UTF-8解码器必须预期UTF-16代理对。