如何将PWSTR转换为C ++中的string?

我有以下代码:

// Fetch Local App Data folder path. PWSTR localAppData = (PWSTR) malloc(128); SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData); // Find out the absolute path to chrome.exe stringstream ss; ss << localAppData << "/Google/Chrome/Application/chrome.exe"; 

stringstreamer的.str()的结果是008F6788/Google/Chrome/Application/chrome.exe ,这是错误的。

我似乎无法得到stringstreamer工作,既没有strcat或wcsncat由于types不兼容。

我如何将这个PWSTRstring?

喔!

微软说 :

 typedef wchar_t* LPWSTR, *PWSTR; 

所以让我们从测试用例中拿出那些可怕的废话,然后丢掉C垃圾:

 // Fetch Local App Data folder path. wchar_t* localAppData = new wchar_t[128]; SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData); stringstream ss; ss << localAppData << "/Google/Chrome/Application/chrome.exe"; delete[] localAppData; 

2.警告!

这里有一个严重的缺陷。

SHGetKnownFolderPath实际上设置你指定给它的指针的值,指向分配的内存。 你的代码有一个内存泄漏,我的最后一个片段错误地微妙地释放内存。

我们通过阅读文档来解决这个问题:

ppszPath [out]

 Type: PWSTR* 

当此方法返回时,包含指向已知文件夹路径的以空字符结尾的Unicode字符串的指针地址。 调用进程负责通过调用CoTaskMemFree来释放不再需要的资源。 返回的路径不包含尾部反斜杠。 例如,返回“C:\ Users”而不是“C:\ Users \”。

 // Fetch Local App Data folder path. wchar_t* localAppData = 0; SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData); stringstream ss; ss << localAppData << "/Google/Chrome/Application/chrome.exe"; CoTaskMemFree(static_cast<void*>(localAppData)); 

现在,在展会上。


3.宽字符

你的代码的语法问题是localAppData是一个wchar_t ,但是正常的stringstreamchar工作。

幸运的是,有一个名为wstringstream的宽字符变体,它使用wchar_t

(请注意,这意味着您的文字必须使用L字符串文字前缀也由wchar_t s构建。)

现在最后的代码是:

 // Fetch Local App Data folder path. wchar_t* localAppData = 0; SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData); wstringstream ss; ss << localAppData << L"/Google/Chrome/Application/chrome.exe"; CoTaskMemFree(static_cast<void*>(localAppData)); 

PWSTR是一个指向宽字符字符串的指针。 你需要

 // Fetch Local App Data folder path. PWSTR localAppData = (PWSTR) malloc(128); SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData); wstringstream ss; ss << localAppData << L"/Google/Chrome/Application/chrome.exe"; 

此外, malloc参数指示要分配的字节数,所以您分配的缓冲区只能容纳64个宽字符(包括NULL字符)。 你可能想使用malloc( 128 * sizeof(wchar_t) )

编辑:
SHGetKnownFolderPath的文档

ppszPath当此方法返回时,包含指向已知文件夹路径的以空字符结尾的Unicode字符串的指针地址。 调用进程负责通过调用CoTaskMemFree释放不再需要的资源

所以你不应该为函数的最后一个参数分配任何内存。

 wchar_t *localAppData = NULL; ::SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData); wstringstream ss; ss << localAppData << L"/Google/Chrome/Application/chrome.exe"; ::CoTaskMemFree(localAppData); 

您不能将一个宽字符的字符串“投”到一个字符串。 原因(2字节单位VS. 1字节单位问题除外)是这个“cast”是不明确的。

什么是源编码? 什么是目的地编码? 在这种情况下,源编码可能是Unicode(外壳扩展可能会返回随机废话,没有任何保证,如果他们不使用Unicode,他们执行有效的X到Unicode转换)。 目标编码很可能是ASCII,尽管它在技术上必须与系统的当前代码页匹配。

如果你想要一个有损Unicode到ASCII的转换,你可以使用WideCharToMultiByte()

我喜欢Praetorina的 Praetorian的答案,只是使用宽字符串流,但如果你想转换:

 char str[128]; wcstombs(str, localAppData, 128); 

还有另一个功能也是相反的:

 wchar_t wstr[128]; mbstowcs(wstr, "Hello World", 128); 

如果你不喜欢widechar,并且想要ansi字符串,请尝试使用wcstombs或WideCharToMultiByte。

要调用SHGetKnownFolderPath,你不需要自己分配内存,这会导致内存泄漏。