我很难将字符串转换为LPWSTR
,因此我可以使用PathStripToRoot()
函数。
MSDN文档说我需要LPTSTR
变量(http://msdn.microsoft.com/en-us/library/windows/desktop/bb773757(v=vs.85).aspx),但Visual Studio 2013说我需要LPWSTR
。
以下是我的功能的代码段:
fileStat fileCreate(const string& targetFile)
{
fileStat filez;
fstream file(targetFile.c_str());
if (!file)
{
cout << "File does not exist" << endl;
}
std::ifstream in(targetFile, ios::binary | ios::ate);
int a = in.tellg();
cout << "File size(bytes): " << in.tellg() << endl << endl;
file.close();
wstring stemp = strChange(targetFile);
LPCWSTR result = stemp.c_str();
/* Tried the below code but that did not work
LPWSTR ws = new wchar_t[targetFile.size() + 1];
copy(targetFile.begin(), targetFile.end(), ws);
ws[targetFile.size()] = 0;
*/
cout<<"\n\n"<<PathStripToRoot(ws)<<"\n\n";
...
filez.fileSize = a;
return filez;
}
很多人都说使用MultiByteToWideChar()
功能,但我查看了MSDN文档并且不知道它是如何工作的。有没有比使用MultiByteToWideChar()
更简单的方法?
答案 0 :(得分:2)
在处理Win32 API时,您可能希望在现代Windows应用程序中使用Unicode UTF-16字符串:使用Visual C ++,std::wstring
类(基于wchar_t
)可以正常使用。
然后,您可以使用方便的字符串类而不是原始的C类字符串缓冲区将Win32 C API PathStripToRoot()
包装在某些C ++代码中。
以下面的注释代码为例:
// Set Unicode mode
#define UNICODE
#define _UNICODE
// Windows SDK Headers
#include <Windows.h> // Win32 Platform SDK
#include <Shlwapi.h> // For PathStripToRoot()
#include <Strsafe.h> // For StringCchCopy()
// Standard C++ Headers
#include <exception> // For std::exception
#include <iostream> // For console output
#include <stdexcept> // For std::invalid_argument, std::runtime_error
#include <string> // For std::wstring
// For using PathStripToRoot()
#pragma comment(lib, "Shlwapi.lib")
// C++ wrapper around PathStripToRoot() Win32 API
std::wstring RootFromPath(const std::wstring& path)
{
// Buffer for PathStripToRoot()
wchar_t pathBuffer[MAX_PATH];
// Copy the input string into the buffer.
// Beware of buffer overruns!
HRESULT hr = ::StringCchCopy(pathBuffer, // dest
_countof(pathBuffer), // dest size
path.c_str()); // source
if (hr == STRSAFE_E_INSUFFICIENT_BUFFER)
{
// Copy failed due to insufficient buffer space.
// May accept this case or throw an exception
// based on the context...
// In this case, I just throw here.
throw std::invalid_argument("RootFromPath() - Path string too long.");
}
if (hr != S_OK)
{
throw std::runtime_error("RootFromPath() - StringCchCopy failed.");
}
// Call the Win32 C API using the raw C buffer
if (! ::PathStripToRoot(pathBuffer))
{
// No valid drive letter was found.
// Return an empty string
return std::wstring();
}
// Return a std::wstring with the buffer content
return std::wstring(pathBuffer);
}
// Test
int main()
{
try
{
const std::wstring path = L"C:\\Path1\\Path2";
const std::wstring root = RootFromPath(path);
std::wcout << "The content of the path before is:\t" << path << std::endl;
std::wcout << "RootFromPath() returned: \t" << root << std::endl;
}
catch(const std::exception& ex)
{
std::cerr << "\n*** ERROR: " << ex.what() << std::endl;
}
}
从命令行编译:
C:\Temp\CppTests>cl /EHsc /W4 /nologo TestPathStripToRoot.cpp
<强>输出:强>
C:\Temp\CppTests>TestPathStripToRoot.exe The content of the path before is: C:\Path1\Path2 RootFromPath() returned: C:\
关于你问题的这一点:
对于一个MSDN文档说我需要
LPTSTR
变量,但是 Visual Studios说我需要LPWSTR
。
LPTSTR
是与TCHAR*
等效的typedef
LPWSTR
是与WCHAR*
等效的typedef,即wchar_t*
。
TCHAR
是字符类型的占位符,可以扩展为char
或wchar_t
,具体取决于您是ANSI / MBCS还是Unicode构建模式。
自VS2005以来,Visual Studio一直使用 Unicode 版本作为默认值。
因此,除非您要维护一个必须使用ANSI / MBCS的旧版应用程序,否则只需在现代Win32应用程序中使用Unicode 。在这种情况下,您可以直接使用基于wchar_t
的字符串和Win32 API,而无需使用旧的过时TCHAR模型。
请注意,您的代码仍然可以std::string
(基于char
),例如表示Unicode UTF-8 文本。您可以在Win32 API边界之间转换UTF-8(char
/ std::string
)和UTF-16(wchar_t
/ std::wstring
)。
为此,您可以使用some convenient RAII wrappers to raw Win32 MultiByteToWideChar()
and WideCharToMultiByte()
APIs。
答案 1 :(得分:2)
考虑构建Windows应用程序的正确方法是假装不存在8位字符串。否则,字符串的编码将根据用户的语言设置而有所不同,并且您的应用程序将无法“全局就绪”,因为总会有一些字符无法通过用户的当前设置表示。 Win32中的8位字符串是20世纪90年代的遗留产品,一个好的Win32应用程序在任何地方使用PWSTR
。请注意,例如在Windows CE或WinRT上,“A函数”甚至不存在,这应该会给你一些微软对这个问题的看法。
现在,实际上,您可能正在使用使用8位字符串的非Windows特定代码进行交互。 IMO使用的最佳方法是按惯例,所有这些字符串都是UTF-8,并使用MultiByteToWideChar
和WideCharToMultiByte
来转换为PWSTR
。请务必使用CP_UTF8
。但对于Windows特定代码,请定义UNICODE
和_UNICODE
宏,忘记TCHAR
,TSTR
,*A
函数和其他此类历史事件存在并在任何地方使用PWSTR
和WCHAR
。你的代码将更加健全。
答案 2 :(得分:0)
您可以使用ATL转换宏:
cout<<"\n\n"<<PathStripToRoot(CA2T(targetFile.c_str()))<<"\n\n";
答案 3 :(得分:0)
如果targetFile是ASCII字符串,请使用PathStripToRootA。在这里你不需要任何转换,targetFile.c_str()将起作用。 如果targetFile是UTF8字符串,请使用MultiByteToWideChar将其转换为WideChar。然后使用PathStripToRoot。 否则make targetFile wstring,将其传递给API而不进行任何转换。
答案 4 :(得分:0)
请完成 Unicode Programming Summary
有几种方法可以解决这个问题。
正确的方法是用_T()括起字符串定义。 PathStripToRoot定义为
#ifdef _UNICODE
#define PathStripToRoot PathStripToRootA
#else
#define PathStripToRoot PathStripToRootW
#endif
_T,Windows API遵循您在项目设置下为项目定义的字符集支持。如果您将文件名作为单字节字符串(string
保存ANSI字符串),请使用PathStripToRootA
。您可以避免将文件名之间转换为UNICODE
字符串。