将字符串转换为LPWSTR

时间:2014-06-10 14:14:46

标签: c++ string winapi unicode

我很难将字符串转换为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()更简单的方法?

5 个答案:

答案 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是字符类型的占位符,可以扩展为charwchar_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,并使用MultiByteToWideCharWideCharToMultiByte来转换为PWSTR。请务必使用CP_UTF8。但对于Windows特定代码,请定义UNICODE_UNICODE宏,忘记TCHARTSTR*A函数和其他此类历史事件存在并在任何地方使用PWSTRWCHAR。你的代码将更加健全。

答案 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字符串。