将变体BSTR转换为std::string的默认编码

8

我有一个变量bstr,它是从MSXML DOM中提取的,因此它是UTF-16编码。我正在尝试弄清楚这种转换所发生的默认编码:

VARIANT vtNodeValue;
pNode->get_nodeValue(&vtNodeValue);
string strValue = (char*)_bstr_t(vtNodeValue);

经过测试,我认为默认编码可能是Windows-1252或Ascii,但不确定。

顺便说一下,这是我正在修复的代码块,将变量转换为wstring,并使用WideCharToMultiByte调用进行多字节编码。

谢谢!

2个回答

10
operator char* 方法调用 _com_util::ConvertBSTRToString()。根据文档,该方法使用当前区域设置执行转换。更新:在内部,_com_util::ConvertBSTRToString() 调用 WideCharToMultiByte,将所有代码页和默认字符参数都设为零。这等同于传递 CP_ACP,表示使用系统当前的 ANSI 代码页设置(而不是当前线程设置)。如果要避免数据丢失,您应该直接调用 WideCharToMultiByte 并使用 CP_UTF8。您仍然可以将字符串视为以空字符结尾的单字节字符串并使用 std::string,但不能将字节视为字符。

2
US Windows的默认代码页是1252,这与我观察到的一致。可以通过此调用在任何计算机上确定: int nCodePage = GetACP(); - Paul

0

std::string本身并不指定/包含任何编码。它只是一系列字节。同样适用于std::wstring,它只是一系列wchar_t(在Win32上是双字节单词)。

通过其operator char*_bstr_t转换为char*,您将简单地获得指向原始数据的指针。根据MSDN,此数据由宽字符组成,即表示UTF-16的wchar_t

我很惊讶它实际上可以从中构造一个std::string;如果您的原始字符串是英语,您不应该通过第一个零字节(很快就会出现)。

但是,由于wstringwchar_t的字符串,因此您应该能够直接从_bstr_t构造一个,如下所示:

_bstr_t tmp(vtNodeValue);
wstring strValue((wchar_t*)tmp, tmp.length());

我不确定length是指字节数还是字符数?然后,你会得到一个以UTF-16编码的wstring,你可以在上面调用WideCharToMultiByte


不对,这并不是真正的强制类型转换,bstr_t有一个operator char*被定义在内部进行转换。 - Tim Sylvester
我知道。单词“cast”不合适吗?也许“转换运算符”更好。我会改变它。 - Thomas
这是不正确的:将 _bstr_t 强制转换为 char* 会调用 _com_util::ConvertBSTRToString 函数将字符串转换为基于字节的编码。 - interjay
我猜你可以称之为强制类型转换,但你绝对不仅仅是获取宽字符数据的指针。 - Tim Sylvester
这些运算符可用于提取封装的Unicode或多字节BSTR对象的原始指针。这些运算符返回指向实际内部缓冲区的指针,因此无法修改生成的字符串。 没有提到任何转换。MSDN有误吗? - Thomas
1
@Thomas 我怀疑该语句的意图是表明您不需要释放结果。该语句没有说出但只是暗示了实际上有两个内部缓冲区。(实际上相当令人困惑,因为它们说“the”指向“the”内部缓冲区。)根据您使用的运算符,您会得到一个不同的指针值,而不仅仅是指向相同地址的不同类型的指针。既然有宽缩小缓冲区,进一步暗示了bstr_t必须进行内部编码转换。 - Tim Sylvester

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