如何使用 Unicode 集将 std::string 传递给 CreateDirectory
Posted
技术标签:
【中文标题】如何使用 Unicode 集将 std::string 传递给 CreateDirectory【英文标题】:How to pass std::string to CreateDirectory with Unicode set 【发布时间】:2015-02-28 07:43:14 【问题描述】:我在使用 CreateDirectory 函数时遇到了困难。在下面的代码中,我得到一个 “无法将参数 1 从 'const char *' 转换为 'LPCWSTR'” CreateDirectory 调用的编译错误。
// make path to folder in program data
char szPath[MAX_PATH];
if ( ! SUCCEEDED( SHGetFolderPathA( NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath ) ) )
std::cout << "ERROR: Could not open server log - no common data folder " << std::endl;
exit(1);
std::string fname = szPath;
fname +="/Point";
CreateDirectory( fname.c_str(), NULL);
我正在使用 Visual Studio 2015 并且有“字符集 = 使用 Unicode 字符集”。
在fileapi.h中定义如下:
#ifdef UNICODE
#define CreateDirectory CreateDirectoryW
#else
#define CreateDirectory CreateDirectoryA
#endif // !UNICODE
所以我认为正在使用 CreateDirectoryW 函数
我需要做什么才能正确编译?
【问题讨论】:
【参考方案1】:您需要使用std::wstring
而不是std::string
才能使用宽字符串。
int main()
// make path to folder in program data
wchar_t szPath[MAX_PATH];
if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath)))
std::cout << "ERROR: Could not open server log - no common data folder " << std::endl;
exit(1);
std::wstring fname = szPath;
fname += L"/Point";
CreateDirectory(fname.c_str(), NULL);
如果您不想使用宽字符串,则需要显式调用窄字符版本的 Windows API 函数,例如 CreateDirectoryA
而不是 CreateDirectory
。
【讨论】:
【参考方案2】:使用CreateDirectoryA
。
也就是说,您最好在应用程序中更改为 Unicode,宽文本。
原代码有一些问题:
// make path to folder in program data
↑ 此评论具有误导性:代码是关于寻找路径,而不是创建路径。
char szPath[MAX_PATH];
↑ 这个缓冲区是不必要的,相反,对于这段代码,你应该在这里声明后面的变量std::string fname
,并指定缓冲区大小。
if ( ! SUCCEEDED( SHGetFolderPathA( NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath ) ) )
↑ !SUCCEEEDED
是对惯用 FAILED
的误导性重写。 SHGetFolderPath
已被弃用。相反,您应该使用SHGetKnownFolderPath
。
std::cout << "ERROR: Could not open server log - no common data folder " << std::endl;
exit(1);
↑ 控制台输出使得这种故障处理在 GUI 程序中几乎没有价值。无论如何,您应该使用cerr
或clog
而不是cout
(默认情况下它们都映射到标准错误流)。在exit
调用中,您应该使用诸如EXIT_FAILURE
之类的标准值,或者提供您得到的HRESULT
(这是Windows 约定,特别是对于崩溃程序),或者对于某些函数,该值你来自GetLastError
。无论如何exit
太激烈了。您应该要么抛出异常,要么返回一个可选项。
std::string fname = szPath;
fname +="/Point";
↑ 通常支持正斜杠,但 Windows 约定仍将反斜杠作为项目分隔符。
CreateDirectory( fname.c_str(), NULL);
↑ 在包含windows.h
之前定义的UNICODE
无法编译的唯一问题。使用CreateDirectoryA
。或者更好的是,切换到 Unicode。
【讨论】:
Hej Alf.您能否详细说明您的评论“切换到 Unicode”?我正在寻找的是最佳实践。程序的其余部分是为在多个平台上工作而编写的,即 OS X 和 64 位。 @user2235373:对于纯 Windows 应用程序切换到 Unicode 就像在包含windows.h
之前定义 UNICODE
并使用宽文本一样简单,即基于 wchar_t
类型,加上一点支持控制台输出。对于具有宽文本方法的可移植代码,您需要在 Unix 领域提供不同的控制台输出支持(基本上只是调用 setlocale
)。但是,使用第 3 方 Unix-land 库,仅使用宽文本的方法不一定可行。相反,我建议使用抽象层,以便相同的代码在 Windows 中使用宽文本 (UTF-16),在 *nix 中使用窄文本 (UTF-8)以上是关于如何使用 Unicode 集将 std::string 传递给 CreateDirectory的主要内容,如果未能解决你的问题,请参考以下文章
MASM 程序集将 8 位寄存器移动到 16 位寄存器(即 mov cx,ch)[重复]