如何在iOS中将UTF-8字符串转换为wchar?

3
我有一个Win32函数需要移植到iOS:
// Loads UTF-8 file and converts to a UTF-16 string

bool LoadUTF8File(char const *filename, wstring &str)
{
    size_t size;
    bool rc = false;
    void *bytes = LoadFile(filename, &size);
    if(bytes != 0)
    {
        int len = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)bytes, size, 0, 0);
        if(len > 0)
        {
            str.resize(len + 1);
            MultiByteToWideChar(CP_UTF8, 0, (LPCCH)bytes, size, &str[0], len);
            str[len] = '\0';
            rc = true;
        }
        delete[] bytes;
    }
    return rc;
}

// LoadFile returns the loaded file as a block of memory
// There is a 3 byte BOM which MultiByteToWideChar seems to ignore
// The text in the file is encoded as UTF-8

我正在使用C++,而不是Objective C,并且一直在尝试使用mbstowcs和_mbstowcs_l。它们似乎与MultiByteToWideChar的行为不同。例如,单词attaché末尾的重音字符未被正确转换(Win32版本正确转换)。是否在标准库中有“UTF-8到UTF-16”的功能?
Win32版本中是否存在我没有注意到的错误?
从MultiByteToWideChar返回的长度小于从mbstowcs返回的长度。
奇怪的是,在这个小测试案例中
    char *p = "attaché";

    wstring str;
    size_t size = strlen(p);
    setlocale(LC_ALL, "");
    int len = mbstowcs(null, p, size);
    if(len > 0)
    {
        str.resize(len + 1);
        mbstowcs(&str[0], p, size);
        str[len] = '\0';
    }
    TRACE(L"%s\n", str.c_str());

    len = MultiByteToWideChar(CP_UTF8, 0, p, size, null, 0);
    if(len > 0)
    {
        str.resize(len + 1);
        MultiByteToWideChar(CP_UTF8, 0, p, size, &str[0], len);
        str[len] = '\0';
    }
    TRACE(L"%s\n", str.c_str());

我使用mbcstowcs得到了正确的输出,但MultiByteToWideChar将最后一个字符错误地转换为65533(REPLACEMENT_CHARACTER)。现在我很困惑...


在运行 mbstowcs 之前,你是否调用了 setlocale(""); - Kerrek SB
谢谢这个 - 我没有,但是恐怕这不会改变我的行为。 - Charlie Skilbeck
也许我的这两个问题会引起一些兴趣:#1, #2 - Kerrek SB
1
请参见https://dev59.com/TXVC5IYBdhLWcg3w51ry。 - Mark Ransom
对于您的测试用例,源文字面值是否可能不是UTF-8编码?请对其进行二进制转储。 - Mark Ransom
显示剩余3条评论
1个回答

0

你是被迫使用 C++ 还是只是迄今为止选择了这种方式但也可以尝试使用 Objective-C ?

在 Objective-C 中,你可以使用 [yourUTF8String dataUsingEncoding:NSUTF16StringEncoding] 来获取包含字符串 UTF-16 表示的字节的 NSData。


附加假设:请注意,您在示例中未正确转换的“é”字符也可能是由于您的解决方案可能没有采用NFD形式(或NFC形式)。这意味着,如果“é”字符以NFD形式编码,例如“带有尖音符的字符'e'”,则可能无法正确解释,而NFC形式(例如“带重音的e字符”,即直接预组合字符)则可以。反之亦然。

这只是一个假设,实际上取决于您期望的“é”字符的结果,但检查一下是值得的。


谢谢,这可能会成为解决方案。我想避免这种方式,因为未来还有其他平台,一个通用的解决方案会更好。 - Charlie Skilbeck

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