将非英语字符串存储在std :: string中

时间:2014-03-13 10:02:05

标签: c++ string encoding stdstring wstring

我在std::wstring

中有一个简单的字符串
std::wstring tempStr = _T("F:\\Projects\\Current_자동_\\Cam.xml");

我想将此字符串存储在std::string

我尝试了以下代码,但结果与输入字符串

不同
std::wstring tempStr = _T("F:\\Projects\\Current_자동_\\Cam.xml");
//setup converter
typedef  std::codecvt_utf8_utf16 <wchar_t> convert_type;
std::wstring_convert<convert_type, wchar_t> converter;

//use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
std::string converted_str = converter.to_bytes( tempStr );

输入字符串中的韩语字符串将转换为"ìžë™"

有什么方法可以在std :: string中获得相同的字符串吗?

预期结果:

converted_str应包含 F:\ Projects \ Current_자동_ \ Cam.xml

以下是调试的屏幕截图,显示了3种情况下的3个值(以3种方式进行转换)。但它们都没有达到预期的价值。

Debugging image

5 个答案:

答案 0 :(得分:4)

您的转换代码没问题。

事实上,在UTF-8(您存储在std::string中的字符串)中,字符자동对应于:

자 (UTF-16 0xC790) ---> UTF-8:  EC 9E 90
동 (UTF-16 0xB3D9) ---> UTF-8:  EB 8F 99

如果您运行以下程序,它只打印转换后的UTF-8字节,您将获得此输出:

ec 9e 90 eb 8f 99

#include <iomanip>      // For std::hex
#include <iostream>     // For console output
#include <string>       // For STL strings
#include <codecvt>      // For Unicode conversions

void print_char_hex(const char ch)
{
    auto * p = reinterpret_cast<const unsigned char*>(&ch);
    int i = *p;
    std::cout << std::hex << i << ' ';
}

int main()
{
    std::wstring utf16_str = L"\xC790\xB3D9";

    // setup converter
    typedef  std::codecvt_utf8_utf16<wchar_t> convert_type;
    std::wstring_convert<convert_type, wchar_t> converter;

    // use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
    std::string converted_str = converter.to_bytes( utf16_str );

    // Output the converted bytes (UTF-8)
    for (size_t i = 0; i < converted_str.length(); ++i)
    {
        print_char_hex(converted_str[i]);
    }
    std::cout << std::endl;
}

答案 1 :(得分:0)

我认为最好的解决方案是使用wide-char API打开文件,例如CreateFileW(...);,因为那时你可以直接使用wide-char文件名。

如果无法做到这一点,可能不应将字符串转换为UTF8,而应转换为系统默认的ANSI代码页。 我认为这可能有用:

    char out[200];
    wchar_t * in = L"F:\\Projects\\Current_자동_\\Cam.xml";
    WideCharToMultiByte(CP_ACP, 0, in, 100, out, 100, 0, 0);

或者可能是另一个韩国代码页:

    WideCharToMultiByte(949, 0, in, 100, out, 100, 0, 0);
    WideCharToMultiByte(1361, 0, in, 100, out, 100, 0, 0);
    WideCharToMultiByte(10003, 0, in, 100, out, 100, 0, 0);
    WideCharToMultiByte(20833, 0, in, 100, out, 100, 0, 0);
    WideCharToMultiByte(20949, 0, in, 100, out, 100, 0, 0);
    WideCharToMultiByte(50225, 0, in, 100, out, 100, 0, 0);
    WideCharToMultiByte(50933, 0, in, 100, out, 100, 0, 0);
    WideCharToMultiByte(51949, 0, in, 100, out, 100, 0, 0);

代码页ID可以在这里找到: http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx

祝你好运: - )

答案 2 :(得分:0)

这可以..你可以告诉因为转换回UTF16是有效的..如果你把UTF8字符串写入文件,它也会正确显示。这样,您现在有两种方法可以验证它是否有效。

// UTF16ToUTF8.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <codecvt>

std::wstring ToUTF16(const std::string &data)
{
    return std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(data);
}

std::string ToUTF8(const std::wstring &data)
{
    return std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(data);
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::wstring u16 = L"_자동_";
    std::string u8 = ToUTF8(u16);

    MessageBoxW(NULL, ToUTF16(u8).c_str(), L"", 0);

    std::cin.get();
    return 0;
}

答案 3 :(得分:0)

问题不在您的字符串转换代码中。这是典型的源文件编码问题。 Visual Studio不使用Unicode作为默认值,因此您应该自己将源文件的编码转换为UTF-8。要进行此转换,您可以使用记事本++打开文件,然后点击编码 - >转换为UTF-8

注意1:在VS2010和vs2012中,如果您将非ascii字符写入源文件,Visual Studio现在会向您发出警告并提供进行此转换。

注意2:从你使用宏_T()我预测这只针对Windows。如果您尝试使用gcc构建包含BOM的UTF-8编码源文件,则可能会出现不同的错误。在任何情况下,最好的方法是在运行时从文件中读取UTF-8编码的文本数据。

答案 4 :(得分:0)

您可以将std:string中的UTF-8存储为常规字符序列。这是包含一些有用内容的库,例如length()以及有关索引的所有内容,您可能希望拥有http://utfcpp.sourceforge.net/

对于Windows控制台,您需要将代码页设置为65001,并且将成为UTF-8。

遗憾的是,std::wstring和整个wchar_t事件没有指定任何特定的编码。

顺便说一句,您使用的是Managed C ++,为什么不使用.NET Framework的System::String^?编码没有任何问题。 http://msdn.microsoft.com/ru-ru/library/system.string(v=vs.110).aspx?cs-save-lang=1&cs-lang=cpp