【问题标题】:BSTR conversion to UTF-8BSTR 转换为 UTF-8
【发布时间】:2018-08-24 08:12:47
【问题描述】:

我正在使用 UIAutomation,并且正在努力使用本地化的 BSTR。我在德国,所以有一些特殊字符在 BSTR 中表现得很有趣。我正在记录这些信息,需要将它们以 UTF-8 格式保存以便稍后处理。

我已经尝试了我能找到的关于 WideCharToMultiByte 的每个版本的答案,但这只是将有趣的角色转换为更有趣的角色。如果有人能告诉我我做错了什么,我真的很感激,这真的让我很烦。

所以我尝试了以下两个版本,两次都得到了这个结果(上一个是转换后的,下一个是原始的):

第一个词应该是“Schaltfläche”,第二个词应该是“Fünf”。

我尝试过的代码:

BSTR* origin;
_bstr_t originWrapper(*origin);
char* originChar = originWrapper;
size_t len = strlen(originChar) + 1;
int room = MultiByteToWideChar(CP_ACP, 0, originChar, -1, NULL, 0);
wchar_t* unicodeString = (wchar_t*)malloc((sizeof(wchar_t))*room);
MultiByteToWideChar(CP_ACP, 0, originChar, -1, unicodeString, room);

int size_needed = WideCharToMultiByte(CP_UTF8, 0, unicodeString, -1, NULL, 0, NULL, NULL);
char* utf8Char = (char*) malloc(size_needed);
WideCharToMultiByte(CP_UTF8, 0, unicodeString, -1, utf8Char, size_needed, NULL, NULL);

BSTR* origin;
_bstr_t originWrapper(*origin);
int size_needed = WideCharToMultiByte(CP_UTF8, 0, originWrapper, SysStringByteLen(*origin), NULL, 0, NULL, NULL);
std::string resultingString(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, *origin, SysStringByteLen(*origin), &resultingString[0], size_needed, NULL, NULL);

【问题讨论】:

  • 调试编码问题的第一条规则:始终查看实际字节,因为打印可能会增加额外的编码问题。您的WideCharToMultiByte 调用报告的字节数是多少?
  • BSTR 已经是wchar_t *,为什么要将它们视为本地代码页窄字符串?
  • BSTR 已经是一个指针(指向一个宽字符串),所以BSTR * 有点奇怪。
  • BSTRs 使用 UTF16-LE 编码。用CP_UTF8 调用WideCharToMultiByte 会生成一个UTF-8 编码的字符串。由于我们不知道您如何确定这些是“更有趣”,因此我们无法为您提供帮助。该错误出现在您尝试输出/显示/观察结果的部分。
  • 指针的出现是因为它是从一个将其作为输入变量的函数复制而来的,我对此进行了监督,并将对其进行编辑。对不起。 @MatteoItalia 第一次尝试?那只是因为第二个不起作用,我尝试了另一个问题的片段。显然没有真正考虑过。对于看起来更有趣的角色,我包括了屏幕截图,因为不幸的是我无法复制和粘贴它。首先,我现在要查看字节并向您提供该信息。

标签: c++ windows utf-8


【解决方案1】:

BSTR 是指向 UTF-16 (WCHAR) 字符数据的指针,前面是字符串长度。所以,你通过窄字符串的往返是错误的,你应该直接使用WideCharToMultiByte

std::string BSTRtoUTF8(BSTR bstr) {
    int len = SysStringLen(bstr);
    // special case because a NULL BSTR is a valid zero-length BSTR,
    // but regular string functions would balk on it
    if(len == 0) return "";
    int size_needed = WideCharToMultiByte(CP_UTF8, 0, bstr, len, NULL, 0, NULL, NULL);
    std::string ret(size_needed, '\0');
    WideCharToMultiByte(CP_UTF8, 0, bstr, len, ret.data(), ret.size(), NULL, NULL);
    return ret;
}

要检查转换的有效性不要将结果输出到控制台,因为默认情况下它不支持 UTF-8 输出(它甚至不像 @987654325 那样解释窄字符串@,但在CP_OEM,请看图)。相反,将输出写入文件并使用支持 UTF-8 的可靠编辑器进行检查。

【讨论】:

  • 谢谢,日志文件中还没有 100% 正确,但这似乎是另一个额外的问题。至少它现在符合 UTF-8 并且不再抛出异常:) 哦,我的问题是我忘记了,控制台不支持 UTF-8 -.-
猜你喜欢
  • 1970-01-01
  • 2015-09-21
  • 1970-01-01
  • 1970-01-01
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 2020-06-07
相关资源
最近更新 更多