【问题标题】:Why filename has different bytes after converting UTF16 -> UTF8 -> UTF16 in winapi?为什么在winapi中转换UTF16 -> UTF8 -> UTF16后文件名有不同的字节?
【发布时间】:2016-04-17 01:49:53
【问题描述】:

我有下一个文件:

我使用ReadDirectoryChangesW 读取当前文件夹中的更改。 我得到这个文件的路径:L"TEST Ӡ⬨☐.ipt":

接下来,我要将其转换为 utf8 并返回:

std::string wstringToUtf8(const std::wstring& source) {
  const int size = WideCharToMultiByte(CP_UTF8, 0, source.data(), static_cast<int>(source.size()), NULL, 0, NULL, NULL);
  std::vector<char> buffer8(size);
  WideCharToMultiByte(CP_UTF8, 0, source.data(), static_cast<int>(source.size()), buffer8.data(), size, NULL, NULL);
}

std::wstring utf8ToWstring(const std::string& source) {
  const int size = MultiByteToWideChar(CP_UTF8, 0, source.data(), static_cast<int>(source.size()), NULL, 0);
  std::vector<wchar_t> buffer16(size);
  MultiByteToWideChar(CP_UTF8, 0, source.data(), static_cast<int>(source.size()), buffer16.data(), size);
}

int main() {
    // Some code with ReadDirectoryChangesW and 
    // ...
    // std::wstring fileName = "L"TEST Ӡ⬨☐.ipt""
    // ...

    std::string filenameUTF8 = wstringToUtf8(fileName);
    std::wstring filename2 = utf8ToWstring(filenameUTF8);
    assert(filenameUTF8 == filename2); // FAIL!
    return 0;
}

但我发现断言。 文件名2:

不同的位:[29]

为什么?

【问题讨论】:

  • 一方面你没有返回你的字符串......你在函数内部使用向量,但在返回类型中使用字符串。

标签: c++ c winapi encoding utf-8


【解决方案1】:

57216 似乎属于代理对范围,在 UTF-16 中用于编码非 BMP 代码点。它们需要成对给出,否则解码不会给你正确的代码点。

65533 是解码器给出的特殊错误字符,因为缺少其他代理项。

换句话说:您的原始字符串不是有效的 UTF-16 字符串。

More info on Wikipedia.

【讨论】:

  • 调试器为57216画一个正方形也是由于代理的原因。
  • 当然可以将无效代理转换为 UTF-8 并原封不动地返回。有点遗憾的是,Microsoft 函数不这样做,因为这意味着您不能可靠地使用它们对文件名进行编码。
  • @HarryJohnston 即使可能,代理项(包括完整的和无效的)在 UTF-8 中都是非法的。因此,功能通过不让它们按原样通过来做正确的事情。但我认为最好的办法是停止并将错误代码作为默认行为,并允许程序员使用可选标志参数选择其他行为(错误字符替换或代理保存)。
  • 我想一个可选标志就可以了,尽管文档必须非常明确地拼出“在处理文件名时必须使用这个标志”,即使那样,太多的程序员也不会阅读它.如果遇到无效字符,已经有一个标志会导致函数失败,但这不是默认值。似乎没有“确保转换是可逆的”的标志。
  • (嗯。在 Windows Vista 之前,这种行为正是我想要的。所以当前的行为完全是故意的,大概是出于标准合规性的原因。)
猜你喜欢
  • 1970-01-01
  • 2013-05-29
  • 2020-09-18
  • 2016-02-20
  • 2012-11-04
  • 2012-02-13
  • 1970-01-01
  • 2016-07-09
  • 2014-02-24
相关资源
最近更新 更多