【问题标题】:CFStringTokenizer's token range in a UTF8 C stringCFStringTokenizer 在 UTF8 C 字符串中的标记范围
【发布时间】:2011-12-29 00:01:19
【问题描述】:

我正在使用 CFStringTokenizer 将大量文本分解为单词,但我在桥接 CFString 使用的任何编码和 UTF8 时遇到了困难。考虑一下:

NSString *theString = @"Lorem ipsum dolor sit amet!";

const char *theCString = [theString cStringUsingEncoding:NSUTF8StringEncoding];

tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, 
                                    (__bridge CFStringRef)theString, 
                                    CFRangeMake(0, [theString length]), 
                                    kCFStringTokenizerUnitWordBoundary, 
                                    locale);

while ((tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)) != kCFStringTokenizerTokenNone) {
    tokenRange = CFStringTokenizerGetCurrentTokenRange(tokenizer);
    memcpy(resultPtr, theCString+tokenRange.location, tokenRange.length);
}

不幸的是,如果遇到任何非 ascii 字符,则在尝试从 C 字符串中读取时,标记器报告的范围不正确。如何从标记器中获取正确的范围,以便能够从我的 C 字符串中提取正确的字符?

为了澄清,memcpy 的东西比上面的要复杂一些,并且对于我的目标设备 iPhone 上的性能是必需的。所以我什至不能做任何事情,比如创建一个 CFString 子字符串并转换它,我需要 C 字符串中的范围。有没有办法在不重新实现各种单词边界库以使其适用于我需要使用的各种不同语言环境的情况下做到这一点? (这是尽可能多的,所以我不能只是迭代寻找''不幸..)

亚历克

【问题讨论】:

    标签: ios cocoa-touch cocoa core-foundation


    【解决方案1】:

    NSStrings 和 CFStrings 处理 UTF-16,而不是 UTF-8,但这不是真正的问题。

    你的代码有两个问题:

    1. 您假设 C 字符串的索引对应于源字符串的索引。
    2. 您正在一次复制整个字符串并将其转换为 UTF-8 C 字符串。

    #1 是范围不匹配的原因,而#2 可能导致高内存使用,具体取决于字符串的长度和内容。 (UTF-8 在某些字母表中每个字符最多可以占用四个字节,然后为 C 字符串终止符添加一个字节。)

    您可以在一次更改中解决这两个问题。

    创建一个 NSMutableData 来保存输出。对于每个标记,将数据的长度设置为范围的length;然后,告诉字符串以所需编码获取所需范围内的字节,并将它们存储在数据的mutableBytes 缓冲区中。 NSString 有 a method with a very long selector(简而言之,getBytes:::::::),您将要使用它。

    由于您将相对于字符串的范围与字符串独占使用,因此没有索引/范围不匹配,并且每个标记都会正确输出。

    如果你真的需要一个 C 字符串,你可以将数据的长度设置为范围的length + 1,然后将最后一个字节设置为'\0',并在获取令牌字节后单独分配。 (如果没有单独的赋值,字节可能会保存以前的值。)

    【讨论】:

    • 谢谢彼得,我现在使用 getBytes 得到了它,范围问题已经解决。我想避免这样的方法,但是因为它在 iPhone 上增加了太多的开销,现在这个算法大约需要 60% 的时间,其余的工作也不是微不足道的。不幸的是,没有 getBytes 的“NoCopy”变体(我知道吗?)所以我认为我在优化方面已经走到了尽头..
    • @Alec:您可能想问另一个问题,说明您打算如何处理 UTF-8 数据。
    猜你喜欢
    • 1970-01-01
    • 2017-09-29
    • 1970-01-01
    • 2014-08-04
    • 2013-04-22
    • 2012-04-27
    • 1970-01-01
    • 2010-09-20
    • 2011-05-31
    相关资源
    最近更新 更多