将转义的UTF8字符转换回它们的原始形式

15

我正在尝试从一个来自plist的数组中读取字符串并打印这些字符串。

数组中的字符串包含转义的UTF8字符-例如,当从plist中读取时,“Nuša Florjančič”变为"Nu\u0161a Florjan\u010di\u010d"。无法更改plist的内容,但我的程序需要正确显示名称。

奇怪的是,当我在硬编码字符串时,Objective-C似乎会自动进行此操作。但是,如果我从plist获取字符串,则根本不会发生任何事情。

为了举例说明,这里有一些代码:

NSString *name1 = @"Nu\u0161a Florjan\u010di\u010d";
NSString *name2 = [list objectAtIndex:0];       
NSLog(@"name 1: %@", name1);
NSLog(@"name 2: %@", name2);

[list objectAtIndex:0] 包含 @"Nu\u0161a Florjan\u010di\u010d" - 唯一的区别是它是通过 plist 编辑器设置的。

控制台输出为:

2011-10-22 18:00:02.595 Test[13410:11c03] name 1: Nuša Florjančič
2011-10-22 18:00:02.595 Test[13410:11c03] name 2: Nu\u0161a Florjan\u010di\u010d

我尝试了各种方法,包括将字符串转换为C字符串,然后使用UTF-8编码创建一个NSString对象,但一点用都没有。

如果您能提供任何指导,帮助我解决这个看似平凡的问题,我将不胜感激。

2个回答

40

听起来你的plist文件中的字符串包含"\u0161"字符,而不是Unicode字符号0x161。因此,你需要解码从plist中提取的字符串中的\u转义字符。 NSString可以使用NSNonLossyASCIIStringEncoding方法为你完成解码:

#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
    @autoreleasepool {
        NSString *name2escaped = @"Nu\\u0161a Florjan\\u010di\\u010d";
        NSString *name2 = [NSString
            stringWithCString:[name2escaped cStringUsingEncoding:NSUTF8StringEncoding]
            encoding:NSNonLossyASCIIStringEncoding];
        NSLog(@"name2 = %@", name2);
    }
    return 0;
}

1
这个解决方案与使用CFStringTransform相比,在两者的优缺点方面有何区别?这对我来说是新的。 - uchuugaka
@uchuugaka 首先,告诉我如何使用 CFStringTransform 来执行此转换。 - rob mayoff
布尔型 CFStringTransform ( CFMutableStringRef string, CFRange *range, CFStringRef transform, Boolean reverse ); 基本上,您提供一个CFMutableString、要操作的范围、ICU转换作为字符串(或包装了一小部分的CF常量之一),最后是一个布尔值,用于确定是否按照提供的转换字符串顺序进行转换或反转它(例如“Hex-Any”)。相同的ICU转换在Cocoa中的其他地方也被使用,并且可以在Java中找到。Cocoa在许多地方都使用ICU库。 - uchuugaka
请给我展示一个使用 CFStringTransform 进行此转换的例子。 - rob mayoff
1
@robmayoff 看看这个答案 https://dev59.com/JHI95IYBdhLWcg3w5iY4#11615076 来了解一个例子。 - Nikolai Ruhe

1
另一个解决方案是解析您的列表字符串(我之前就用过解析它)。
NSString yourFinalString = [NSString stringWithCString:[yourOriginalString cStringUsingEncoding:NSISOLatin1StringEncoding] encoding:NSUTF8StringEncoding];

看起来像是克罗地亚语,我认为Latin1会更适合。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接