V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
pheyer
V2EX  ›  iOS

汉字使用 cString 转换的乱码问题

  •  
  •   pheyer · 2022-06-14 11:14:17 +08:00 · 1690 次点击
    这是一个创建于 893 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假如给定一串乱码Âà†Èô§Â§±Ë¥•,已知它的实际内容为 4 个汉字,你能这些乱码恢复出真实的汉字出来吗?

    我使用几个提供乱码文字恢复服务的网站,都没能把它恢复出来。

    其实这段乱码是这样产生的:见下面的代码,对于指定汉字字符串,先转换为 c 字符串,再使用 initWithCString 转换为 NSString ,得到的结果为Âà†Èô§Â§±Ë¥•,length 是 12 ,但是字节数为 26

    NSString* plain = @"删除失败";
    const char *s = [plain UTF8String];
    NSString* s1 = [[NSString alloc] initWithCString:s];
    

    正确的做法当然是这样的

    NSString* s2 = [[NSString alloc] initWithCString:s encoding:NSUTF8StringEncoding];
    

    initWithCString: 是已被苹果废弃的 api ,我仍然好奇这段乱码是怎么产生的,查看文档没搞清楚它到底用的什么编码导致了这样的乱码。

    4 个汉字的 utf8 字符串对应 12 个字节,乱码中的奇怪字符刚好有 12 个,好像是 1 个 utf8 字节对应一个乱码字符?有人能解惑吗

    13 条回复    2022-06-14 17:29:01 +08:00
    mainjzb
        1
    mainjzb  
       2022-06-14 11:49:07 +08:00
    谷歌搜索-》 乱码恢复
    mainjzb
        2
    mainjzb  
       2022-06-14 11:49:16 +08:00
    mainjzb
        3
    mainjzb  
       2022-06-14 11:50:20 +08:00
    所以大概率:原来编码 GBK 新编码 UTF-8
    pheyer
        4
    pheyer  
    OP
       2022-06-14 12:45:17 +08:00
    @mainjzb 你看我帖子的第 2 行,跟 gbk 编码应该无关的
    PolarBears
        5
    PolarBears  
       2022-06-14 14:25:42 +08:00   ❤️ 1
    MrKrabs
        6
    MrKrabs  
       2022-06-14 14:35:52 +08:00
    s1 是 null 啊
    pheyer
        7
    pheyer  
    OP
       2022-06-14 14:44:24 +08:00
    @PolarBears 这个工具不错,帮助我找到了实际的编码 NSMacOSRomanStringEncoding
    NSString* s1 = [[NSString alloc] initWithCString:s];
    NSString* strRoman = [[NSString alloc] initWithCString:s encoding:NSMacOSRomanStringEncoding];

    以上两行代码效果相同
    pheyer
        8
    pheyer  
    OP
       2022-06-14 14:45:48 +08:00
    @MrKrabs 不是 null ,你打印日志看看
    MrKrabs
        9
    MrKrabs  
       2022-06-14 16:39:03 +08:00
    @pheyer
    NSLog(@"%s %@ %@", s, s1, s2);
    2022-06-14 16:37:50.533004+0800 OCString[20254:11557900] 删除失败 (null) 删除失败
    pheyer
        10
    pheyer  
    OP
       2022-06-14 16:50:08 +08:00
    @MrKrabs 这还真是神奇,我用我的 Xcode13.1 的打印结果是:删除失败 Âà†Èô§Â§±Ë¥• 删除失败
    用的 OS 是 MacOS 11.6 ,用 iPhone XR 测试的,难道你用的模拟器测试的?
    MrKrabs
        11
    MrKrabs  
       2022-06-14 17:16:49 +08:00
    @pheyer 就写了个 main.m 直接在 mac 跑的
    Skifary
        12
    Skifary  
       2022-06-14 17:26:13 +08:00
    字符串乱码都是编码不对造成的。const char *s 可以理解为一堆数据,至于这堆数据按照什么编码解析依靠 NSString 来指定。

    initWithCString 在苹果文档里面有解释

    Initializes the receiver, a newly allocated NSString object, by converting the data in a given C-string from the default C-string encoding into the Unicode character encoding.

    这个函数被弃用了,在初始化的时候有一个 default C-string encoding (默认的编码)来解析这个格式。

    默认的编码格式 NSString 提供了一个 defaultCStringEncoding 来获取,默认值是 30 对应的就是 NSMacOSRomanStringEncoding
    Skifary
        13
    Skifary  
       2022-06-14 17:29:01 +08:00
    @Skifary 一堆 NSUTF8StringEncoding 的数据用 NSMacOSRomanStringEncoding 来解析自然就乱码了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2540 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:35 · PVG 18:35 · LAX 02:35 · JFK 05:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.