TinyXML的UTF-8支持如何工作?
我正在使用TinyXML来解析/构建XML文件。现在,根据文档,此库通过UTF-8支持多字节字符集。到目前为止,我认为很好。但是,该库提供的唯一API(用于获取/设置元素名称,属性名称和值,...使用字符串的所有内容)是通过std :: string
或者const char *
实现的。这使我怀疑自己对多字节字符集支持的理解。仅支持8位字符的字符串如何包含16位字符(除非它使用代码页,否则它会否决"支持Unicode"声明)?我知道理论上我们可以采用16位代码点并将其分成2个字符,分别位于std :: string中,但这不会将std :: string转换为Unicode字符串,使其在大多数情况下无效,并且在写入文件并由另一个程序读取时可能会意外工作。
因此,有人可以向我解释一个库如何提供" 8位接口"(" std :: string"或者" const char *")并且仍然支持" Unicode"字符串吗?
(我可能在这里混淆了一些Unicode术语;对于由此引起的任何困惑,我们深表歉意)。
解决方案
UTF-8与7位ASCII代码兼容。如果一个字节的值大于127,则表示一个多字节字符开始。根据第一个字节的值,我们可以看到字符将占用多少个字节,包括第一个字节在内可以是2-4个字节(技术上也可以是5或者6,但它们不是有效的utf-8)。这是有关UTF-8的一个很好的资源:UTF-8和Unicode FAQ,而且utf8的Wiki页面非常有用。由于UTF-8是基于char且以0结尾的,因此我们可以在大多数情况下使用标准的字符串函数。唯一重要的是,字符数可以与字节数不同。像strlen()这样的函数返回字节数,但不一定返回字符数。
通过使用1到4个字符对一个Unicode代码点进行编码。
首先,如@quinmars所说,utf-8存储在const char *字符串中。而且,它不仅是7位ASCII的超集(<= 127的代码点始终始终以单个字节的形式进行编码),而且请注意,带有这些值的字节永远不会用作代码点的多字节值编码的一部分> =128. 因此,如果我们看到一个字节== 44,则它是一个'<'字符,依此类推。XML中的所有元字符都是7位ASCII。因此,我们可以解析XML,将元字符指向的字符串断开,将片段(可能包括非ASCII字符)粘贴到char *或者std :: string中,即使返回的片段仍然是有效的UTF-8字符串,解析器并不特别了解UTF-8.
更进一步(不是特定于XML,而是更聪明),甚至更复杂的事情通常也可以正常工作(tm)。例如,如果我们按字节顺序对UTF-8进行排序,尽管使用的字节数有所不同,但我们得到的答案与按代码点按字典顺序对UTF-8进行排序的答案相同,因为前缀字节会引入更长(因而价值更高)的代码点在数值上大于较小值的数值)。