2009-12-01 8 views
8

J'ai une variante bstr qui a été extraite de DOM MSXML, elle est donc en UTF-16. J'essaie de comprendre ce que l'encodage par défaut se produit avec cette conversion:Codage par défaut pour la variante bstr en conversion std :: string

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

De test, je crois que le codage par défaut est soit Windows 1252 ou Ascii, mais ne suis pas sûr. Btw, c'est le morceau de code que je corrige et convertit la variante en wstring et passe à un encodage multi-octets avec un appel à WideCharToMultiByte.

Merci!

Répondre

10

La méthode operator char* appelle _com_util::ConvertBSTRToString(). The documentation n'est pas très utile, mais je suppose qu'il utilise les paramètres régionaux en cours pour faire la conversion.

Mise à jour:

En interne, _com_util::ConvertBSTRToString() appels WideCharToMultiByte, passant de zéro pour tous les paramètres du code page et caractère par défaut. Cela équivaut à passer le CP_ACP, ce qui signifie utiliser le paramètre de page de code ANSI actuel du système (pas le paramètre de filetage actuel).

Si vous voulez éviter de perdre des données, vous devez appeler directement WideCharToMultiByte et utiliser CP_UTF8. Vous pouvez toujours traiter la chaîne comme une chaîne à un octet et utiliser std::string, vous ne pouvez pas traiter les octets comme des caractères.

+2

Merci !!! La page de codes par défaut sur Windows US est 1252, ce qui est cohérent avec ce que j'ai observé. Cela peut être déterminé sur n'importe quelle machine avec cet appel: \t int nCodePage = GetACP(); –

0

std::string en lui-même ne spécifie/ne contient aucun codage. C'est simplement une séquence d'octets. La même chose vaut pour std::wstring, qui est simplement une séquence de wchar_t s (mots à deux octets, sur Win32).

En convertissant _bstr_t à un char* par son operator char*, vous obtenez simplement un pointeur vers les données brutes. According to MSDN, ces données sont constituées de caractères larges, c'est-à-dire wchar_t s, qui représentent UTF-16.

Je suis surpris que cela fonctionne effectivement pour construire un std::string à partir de cela; vous ne devriez pas dépasser le premier octet zéro (qui se produit bientôt, si votre chaîne d'origine est l'anglais).

Mais depuis wstring est une chaîne de wchar_t, vous devriez être en mesure de construire un directement à partir du _bstr_t, comme suit:

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

(je ne suis pas sûr de length, est-ce le nombre d'octets ou le nombre de caractères?) Ensuite, vous aurez un wstring qui est codé en UTF-16 sur lequel vous pouvez appeler WideCharToMultiByte.

+0

Ce n'est pas correct, ce n'est pas vraiment un cast, 'bstr_t' a un' operator char * 'défini qui fait la conversion en interne. –

+0

Je sais. Le mot "cast" est-il inapproprié? Peut-être que "l'opérateur de conversion" est meilleur. Je vais le changer. – Thomas

+0

Cela est incorrect: la conversion d'un '_bstr_t' en' char * 'appelle la fonction' _com_util :: ConvertBSTRToString' pour convertir la chaîne en un codage basé sur un octet. – interjay