以utf-8字符串访问字符

时间:2016-07-12 18:59:48

标签: encoding utf-8

首先,我想确保正确理解utf-8的概念。当字符串存储在utf-8中时,每个字符实际上是1-4个字节,具体取决于它所代表的字符。

如果我有这样的ascii字符串:

string meh = "blah";

然后所有要做的就是获取第四个字符是获取指向第一个字符的指针并添加一个大小为char的偏移量来定位字符,如下所示:

meh[3] == *(meh + 3);    // not real code, just pseudo c for what the compiler does

但是,如果我有这样的字符串:

string peh = "blah★!";

我想要感叹号,peh [6]不会检索“!”但★字符中的第二个字节。

那么随机访问该字符的唯一方法是线性搜索吗? (从头开始,每个char检查它的长度跳过那么多,直到我到达正确的字符索引)。如果是这样,为什么每个人都想在utf-8中存储文件?难道这不会让分析和分析变得更加昂贵吗?

(在上下文中,我正在写一个语言词法分析器和周围的信息说源文件应该在utf-8中,但是如果我支持可变长度的字符,那不就是不必要地使所有内容复杂化吗?它是否可以接受?只支持utf-8 / ascii,只包含源文件的单字节字符?)

3 个答案:

答案 0 :(得分:3)

  

那么随机访问该字符的唯一方法是线性搜索吗? (从头开始,每个字符检查它的长度,跳过那么多,直到我达到正确的字符索引)。

是的,确实。

  

如果是这样,为什么每个人都想在utf-8中存储文件?

UTF-8比UTF-16或UTF-32更易于移植(UTF-8没有端序问题),并且向后兼容ASCII,因此它不会破坏绝大多数遗留应用程序。此外,对于Unicode代码点U + 0000 - U + 007F,UTF-8的字节大小比UTF-16更紧凑,并且对于代码点U + 0080-U + 07FF,UTF-8的字节大小与UTF-16相同。因此,UTF-8往往是处理世界上大多数常用英语/拉丁语言的更好选择。但是,一旦你开始处理U + 07FF以上的Unicode代码点(亚洲语言,符号,表情符号等),UTF-16通常会比UTF-8更紧凑

UTF-16在处理数据时往往更容易使用,因为它只处理代码点U + 0000 - U + FFFF的1个代码单元,而UTF-8使用1-3代码单元相同的代码点。 UTF-16使用2个代码单元用于剩余的代码点,而UTF-8则使用4个代码单元用于相同的代码点。

但即便如此,UTF-16在技术上也是一种可变长度编码,因此您也无法真正使用随机访问。只有当数据包含代码点U + 0000 - U + 007F并且没有更高时,才能在UTF-8中进行真正的随机访问,并且只有当数据包含代码点U + 0000 - U + FFFF并且没有更高时,才能在UTF-16中进行真正的随机访问。其他任何东西都需要线性扫描。但是,通过UTF-16扫描比扫描UTF-8更容易,因为涉及的代码单元更少。 UTF-16旨在轻松检测前导和尾随代码单元,以便在扫描过程中跳过它们,而UTF-8也不适用于此。

  

这不会让解析和分析变得更加昂贵吗?

UTF-8更适合存储和通信,但解析时不一定容易。这取决于所涉及的语言。只要您考虑代理对,UTF-16往往更适合解析。

如果您不想处理可变长度字符,并且需要真正的随机访问,那么请改用UTF-32,因为它只为每个可能的代码点使用1个代码单元。

  

在上下文中,我写了一个语言词法分析器和周围的信息说源文件应该是utf-8,但是如果我支持可变长度字符,那不会不必要地使所有内容复杂化吗?

不一定,特别是如果您只支持正向解析。即使使用UTF-16,您也必须考虑可变长度的字符。

  

仅支持utf-8 / ascii只包含源文件的单字节字符是否可以接受?

这取决于解析器的要求,但我会拒绝。许多用户希望能够在其源文件中嵌入Unicode数据,甚至可以使用Unicode标识符。即使在Unicode之前的Ansi日期,非ASCII字符也可以是单字节或多字节,具体取决于所使用的字符集。

因此,除非你想完全避开非ASCII语言(这在今天的国际世界中并不是一个好主意),你应该以一种或另一种形式处理可变长度的字符。

答案 1 :(得分:0)

您正在比较苹果和橘子。 Unicode比ASCII更具表现力;在支持Unicode的流行编码中,UTF-8对于绝大多数情况来说是最简单和最紧凑的,并且与纯ASCII 7位文本的ASCII兼容性是一个巨大的好处。

如果您的代码完全由字符长度计算控制,并且您需要支持Unicode,请考虑在内部使用UTF-32。 (UTF-16也是可变长度的,因为代理对。)

答案 2 :(得分:0)

  

那么随机访问该字符的唯一方法是线性搜索吗?   (从头开始,每个字符检查它的长度跳过那么多,直到我达到正确的字符索引)。

使用Unicode而不是字符,您可以查找代码点。字符的每个概念都以Unicode的唯一编号给出。 UTF-8是编码Unicode代码点的众多方法之一。这意味着如果您正在阅读或编写 UTF-8编码的文本,那么您(或您使用的库)需要知道编码的工作原理。随机访问是字节寻址的。除非您知道给定编码中该字符的确切偏移量,否则随机访问它不会起作用。

  

如果是这样,为什么每个人都想在utf-8中存储文件?

嗯,UTF-8是一种编码方案,支持Unicode标准中指定的字符。如果您曾经要求编写和读取超出的字符,比如ASCII字符集,则必须选择一些编码方案来表示它们,并且人们通过使用最适合其需要的编码来明确指出。确实,这意味着要考虑一些存储要求。但是你是否担心文件的长度而不是消息内容的准确表示?

  

这不会让分析和分析变得更加昂贵吗?

不,如果没有其他方式来表示您期望的角色,那就不是了。如果您知道所有文本都适合ASCII字符集,则无需使用UTF-8进行编码。 (也就是说,UTF-8向后兼容ASCII)。

相关问题