我在关于utf-8的维基百科文章中找到了这个:
将UTF-8字符串排序为无符号字节数组将产生与基于Unicode代码点对它们进行排序相同的结果.
这将使我相信,为了进行比较(排序,二进制搜索等),比较utf-8编码字符串的两个字节数组(即逐字节,如memcmp)将得到与比较实际unicode字符串相同的结果.
这是真的?
是的,鉴于UTF-8编码和Unicode代码点中的序列字节之间存在一对一的映射.
但是,除了查看原始代码点之外,还有比较Unicode字符串的方法.如果您只是将代码点(或UTF-8字节)视为数字,那么您将错过特定于文化的比较逻辑.
要在特定文化上正确实现比较和排序,在.NET上,您应该使用标准字符串比较函数.
它与代码点比较的代码点相同,也就是说不关注大小写折叠,文化排序,组合或除Unicode值之外的任何其他代码点.
考虑字符串作为一块人类可读的文本时,这是相当无用的,但有时你只是希望能够把字符串转换为一个排序,因为一些算法(二进制搜索像你说的),需要一个统一的排序,但在细节上这种一致的排序并不重要.
但值得注意的是,.NET提供的字符串序数比较适用于内部使用的UTF-16,它不支持代码点排序.如果我们将字符串与仅字符U + FF61和仅具有字符U + 10002的字符串进行比较,则.NET将后者存储为代理对,即0xD800和0XDC02.
因此:
string.CompareOrdinal("\U0000ff61", "\U00010002");
Run Code Online (Sandbox Code Playgroud)
和
string.Compare("\U0000ff61", "\U00010002", StringComparison.Ordinal);
Run Code Online (Sandbox Code Playgroud)
两者都返回值大于零,即使前者的代码点值低于后者(我使用\ U形式而不是\ u形式使其更清晰).
如果"实际的unicode字符串"是指.NET UTF-16字符串,那么你的问题的答案是否定的,因为相反的原因导致你认为它可能有效.
这取决于"比较实际的Unicode字符串"的含义.
如果您只是比较代码点(作为32位数字)而不是UTF-8编码的代码点,那么答案是肯定的:这将得到相同的结果.从代码点到UTF-8编码字节的映射是一对一的.
如果你要进行正确的Unicode字符串比较,而不是UTF-8的字节比较,答案是否定的.在Unicode中,可以有不同的方式来表示相同的字符.例如,é可以用(至少)两种方式表示:
U+00e9 (LATIN SMALL LETTER E WITH ACUTE), 要么U+0065 (LATIN SMALL LETTER E)接着是U+0301 (COMBINING ACUTE ACCENT).正确编写的Unicode比较函数将认为这两者是相同的.
| 归档时间: |
|
| 查看次数: |
2140 次 |
| 最近记录: |