简体   繁体   English

如何在C ++中将PWSTR转换为字符串?

[英]How do I convert PWSTR to string in C++?

I have the following code: 我有以下代码:

// 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";

The result of stringstreamer's .str() is 008F6788/Google/Chrome/Application/chrome.exe , which is wrong. stringstreamer的.str()的结果是008F6788/Google/Chrome/Application/chrome.exe ,这是错误的。

I can't seem to get stringstreamer to work, neither do strcat or wcsncat due to type incompatibilities. 我似乎无法使用stringstreamer工作,由于类型不兼容,strcat或wcsncat也没有。

How do I cast this PWSTR to string? 如何将此PWSTR强制转换为字符串?

1. Yuk! Yuk!

Microsoft says : 微软

typedef wchar_t* LPWSTR, *PWSTR;

So let's get that horrid nonsense out of your testcase, and lose the C rubbish: 所以,让我们从你的测试用例中得到那个可怕的废话,并丢失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. Warning! 2.警告!

There is a serious flaw here. 这里有一个严重的缺陷。

SHGetKnownFolderPath actually sets the value of the pointer you give it to point to memory that it allocated. SHGetKnownFolderPath实际上设置了指向它指向分配的内存的指针的值。 Your code has a memory leak, and my last snippet frees the memory subtly wrongly. 你的代码有内存泄漏,我的最后一个代码段错误地释放了内存。

Let's fix that by reading the documentation : 让我们通过阅读文档来解决这个问题:

ppszPath [out] ppszPath [out]

 Type: PWSTR* 

When this method returns, contains the address of a pointer to a null-terminated Unicode string that specifies the path of the known folder. 此方法返回时,包含指向以null结尾的Unicode字符串的指针的地址,该字符串指定已知文件夹的路径。 The calling process is responsible for freeing this resource once it is no longer needed by calling CoTaskMemFree. 调用进程负责通过调用CoTaskMemFree释放不再需要的资源。 The returned path does not include a trailing backslash. 返回的路径不包括尾部反斜杠。 For example, "C:\\Users" is returned rather than "C:\\Users\\". 例如,返回“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));

Now, on with the show. 现在,随着节目。


3. Wide characters 3.广角

The syntax issue with your code is that localAppData is a wchar_t , but normal stringstream s work on char . 您的代码的语法问题是localAppData是一个wchar_t ,但正常的stringstreamchar

Fortunately, there is a wide-char variant called wstringstream that uses wchar_t instead. 幸运的是,有一个名为wstringstream的宽字符变体,它使用wchar_t代替。

(Note that this means your literal will have to be built out of wchar_t s, too, using the L string literal prefix.) (请注意,这意味着您的文字也必须使用L字符串文字前缀从wchar_t构建。)

And now the final code: 现在最后的代码:

// 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 is a pointer to a wide-character string. PWSTR是指向宽字符串的指针。 You need 你需要

// 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";

Also, malloc argument indicates the number of bytes to allocate, so you're allocating a buffer that can only hold 64 wide characters (including the NULL character). 此外, malloc参数指示要分配的字节数,因此您要分配一个只能容纳64个宽字符(包括NULL字符)的缓冲区。 You might want to use malloc( 128 * sizeof(wchar_t) ) . 您可能想要使用malloc( 128 * sizeof(wchar_t) )

EDIT: 编辑:
From the documentation for SHGetKnownFolderPath SHGetKnownFolderPath的文档

ppszPath When this method returns, contains the address of a pointer to a null-terminated Unicode string that specifies the path of the known folder. ppszPath当此方法返回时,包含指向以null结尾的Unicode字符串的指针的地址,该字符串指定已知文件夹的路径。 The calling process is responsible for freeing this resource once it is no longer needed by calling CoTaskMemFree 调用进程负责通过调用CoTaskMemFree释放不再需要的资源

So you shouldn't be allocating any memory for the last argument for the function. 所以你不应该为函数的最后一个参数分配任何内存。

wchar_t *localAppData = NULL;
::SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData);

wstringstream ss;
ss << localAppData << L"/Google/Chrome/Application/chrome.exe";
::CoTaskMemFree(localAppData);

I like Praetorina's Praetorian's answer of just using wide string stream but if you want to convert: 我喜欢 Praetorina的 Praetorian的答案,只是使用宽字符串流,但如果你想转换:

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

There is another function which goes the other way around too: 另一个功能也是相反的:

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

You cannot "cast" a wide-character string to a string. 您不能将宽字符串“强制转换”为字符串。 The reason (other than the 2-byte unit VS. 1-byte unit issue) is that this "cast" would be ambiguous. 原因(除了2字节单位VS. 1字节单位问题)是这个“演员”是不明确的。

What is the source encoding? 什么是源编码? What is the destination encoding? 什么是目的地编码? In this case, the source encoding is likely to be Unicode (shell extensions may return random crap, nothing guarantees that they performed a valid X-to-Unicode conversion if they weren't using Unicode). 在这种情况下,源代码编码可能是Unicode(shell扩展可能会返回随机废话,没有任何保证,如果他们不使用Unicode,他们会执行有效的X到Unicode转换)。 The destination encoding is likely to be ASCII, although it technically has to match the system's current codepage. 目标编码可能是ASCII,虽然它在技术上必须匹配系统的当前代码页。

If you want a lossy Unicode-to-ASCII conversion, you can use WideCharToMultiByte() . 如果您想要有损的Unicode到ASCII转换,可以使用WideCharToMultiByte()

If you don't like widechar and want ansi string badly, try wcstombs or WideCharToMultiByte. 如果您不喜欢widechar并且想要ansi字符串,请尝试使用wcstombs或WideCharToMultiByte。

To call SHGetKnownFolderPath, you don't need to allocate memory by yourself, it will cause memory leak. 要调用SHGetKnownFolderPath,您不需要自己分配内存,这会导致内存泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM