【问题标题】:How to handle 32bit unicode characters in a NSString如何处理 NSString 中的 32 位 unicode 字符
【发布时间】:2013-12-30 12:31:48
【问题描述】:

我有一个包含大于 U+FFFF 的 unicode 字符的 NSString,例如 MUSICAL SYMBOL G CLEF 符号 '????'。我可以创建 NSString 并显示它。

NSString *s = @"A\U0001d11eB";  // "A????B"
NSLog(@"String = \"%@\"", s);

日志正确并显示 3 个字符。这告诉我 NSString 做得很好,没有编码问题。

    String = "A????B"

但是当我尝试使用该方法遍历所有字符时

- (unichar)characterAtIndex:(NSUInteger)index

一切都出错了。

unichar 类型是 16 位,所以我希望得到错误的音乐符号字符。但是字符串的长度也不对!

NSLog(@"Length = %d", [s length]);
for (int i=0; i<[s length]; i++)
{
    NSLog(@"  Character %d = %c", i, [s characterAtIndex:i]);
}

展示

    Length = 4
      Character 0 = A
      Character 1 = 4
      Character 2 = .
      Character 3 = B

我应该使用什么方法来正确解析我的 NSString 并获取我的 3 个 unicode 字符? 理想情况下,正确的方法应该返回像 wchar_t 这样的类型来代替 unichar

谢谢

【问题讨论】:

    标签: objective-c unicode nsstring


    【解决方案1】:
    NSString *s = @"A\U0001d11eB";
    NSData *data = [s dataUsingEncoding:NSUTF32LittleEndianStringEncoding];
    const wchar_t *wcs = [data bytes];
    for (int i = 0; i < [data length]/4; i++) {
        NSLog(@"%#010x", wcs[i]);
    }
    

    输出:

    0x00000041 0x0001d11e 0x00000042

    (代码假设wchar_t的大小为4字节,采用little-endian编码。)

    lengthcharAtIndex: 没有给出预期的结果,因为\U0001d11e 在内部存储为 UTF-16“代理对”。

    通用 Unicode 字符串的另一个有用方法是

    [s enumerateSubstringsInRange:NSMakeRange(0, [s length])
                  options:NSStringEnumerationByComposedCharacterSequences
               usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
        NSLog(@"%@", substring);
    }];
    

    输出:

    一种 ? 乙

    【讨论】:

    • 这完美地回答了我的问题。非常感谢马丁!
    猜你喜欢
    • 2011-10-11
    • 1970-01-01
    • 2012-03-03
    • 2011-11-20
    • 1970-01-01
    • 1970-01-01
    • 2018-12-05
    • 2011-04-23
    • 2017-02-24
    相关资源
    最近更新 更多