我有以下代码:
// 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。
如何将此PWSTR转换为字符串?
答案 0 :(得分:29)
Microsoft says:
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;
这里有一个严重的缺陷。
SHGetKnownFolderPath
实际上设置了指向它的指针的值,指向 it 分配的内存。你的代码有内存泄漏,我的上一个代码片段错误地释放了内存。
让我们通过阅读the documentation:
来解决这个问题ppszPath [out]
Type: PWSTR*
当此方法返回时,包含指向以null结尾的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));
现在,关于节目。
您的代码的语法问题是localAppData是wchar_t
,但正常stringstream
适用于char
。
幸运的是,有一个名为wstringstream
的宽字符变种使用wchar_t
代替。
(请注意,这意味着您的文字也必须使用wchar_t
字符串文字前缀从L
构建。)
现在最后的代码:
// 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));
答案 1 :(得分:4)
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 当此方法返回时,包含指向以null结尾的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 :(得分:3)
我喜欢 Praetorina的 Praetorian的回答只是使用宽字符串流,但如果你想转换:
char str[128];
wcstombs(str, localAppData, 128);
还有另一种功能反过来:
wchar_t wstr[128];
mbstowcs(wstr, "Hello World", 128);
答案 3 :(得分:1)
您不能将宽字符串“强制转换”为字符串。原因(除了2字节单位VS. 1字节单位问题)是这个“演员”是不明确的。
什么是源编码?什么是目的地编码?在这种情况下,源代码编码可能是Unicode(shell扩展可能会返回随机废话,没有任何保证,如果他们不使用Unicode,他们会执行有效的X到Unicode转换)。目标编码很可能是ASCII,尽管技术上必须匹配系统的当前代码页。
如果您想要进行有损的Unicode到ASCII转换,可以使用WideCharToMultiByte()
。
答案 4 :(得分:0)
如果你不喜欢widechar并且想要ansi字符串,请尝试使用wcstombs或WideCharToMultiByte。
要调用SHGetKnownFolderPath,您不需要自己分配内存,这会导致内存泄漏。