2011-08-22 77 views
16

如果我有一個UTF-8 std::string我該如何將它轉換爲UTF-16 std::wstring?其實,我想比較兩個波斯語。如何將UTF-8 std :: string轉換爲UTF-16 std :: wstring?

+0

查看http://stackoverflow.com/questions/148403/utf8-to-from-wide-char-conversion-in-stl等等。 –

+0

[可以如何比較utf8字符串,如C++中的波斯語單詞?](http://stackoverflow.com/questions/7141417/how-can-i-compare-utf8-string-such-as-persian-單詞在C)或[這](http://stackoverflow.com/questions/7141260/compare-stdwstring-and-stdstring)。 –

回答

19

下面是一些代碼。只有輕微的測試,可能有一些改進。調用此函數將UTF-8字符串轉換爲UTF-16字符串。如果它認爲輸入字符串不是UTF-8,那麼它將引發異常,否則它將返回等效的UTF-16字符串。

std::wstring utf8_to_utf16(const std::string& utf8) 
{ 
    std::vector<unsigned long> unicode; 
    size_t i = 0; 
    while (i < utf8.size()) 
    { 
     unsigned long uni; 
     size_t todo; 
     bool error = false; 
     unsigned char ch = utf8[i++]; 
     if (ch <= 0x7F) 
     { 
      uni = ch; 
      todo = 0; 
     } 
     else if (ch <= 0xBF) 
     { 
      throw std::logic_error("not a UTF-8 string"); 
     } 
     else if (ch <= 0xDF) 
     { 
      uni = ch&0x1F; 
      todo = 1; 
     } 
     else if (ch <= 0xEF) 
     { 
      uni = ch&0x0F; 
      todo = 2; 
     } 
     else if (ch <= 0xF7) 
     { 
      uni = ch&0x07; 
      todo = 3; 
     } 
     else 
     { 
      throw std::logic_error("not a UTF-8 string"); 
     } 
     for (size_t j = 0; j < todo; ++j) 
     { 
      if (i == utf8.size()) 
       throw std::logic_error("not a UTF-8 string"); 
      unsigned char ch = utf8[i++]; 
      if (ch < 0x80 || ch > 0xBF) 
       throw std::logic_error("not a UTF-8 string"); 
      uni <<= 6; 
      uni += ch & 0x3F; 
     } 
     if (uni >= 0xD800 && uni <= 0xDFFF) 
      throw std::logic_error("not a UTF-8 string"); 
     if (uni > 0x10FFFF) 
      throw std::logic_error("not a UTF-8 string"); 
     unicode.push_back(uni); 
    } 
    std::wstring utf16; 
    for (size_t i = 0; i < unicode.size(); ++i) 
    { 
     unsigned long uni = unicode[i]; 
     if (uni <= 0xFFFF) 
     { 
      utf16 += (wchar_t)uni; 
     } 
     else 
     { 
      uni -= 0x10000; 
      utf16 += (wchar_t)((uni >> 10) + 0xD800); 
      utf16 += (wchar_t)((uni & 0x3FF) + 0xDC00); 
     } 
    } 
    return utf16; 
} 
+1

謝謝你!謝謝!它的工作......我不能相信它:)謝謝你的時間約翰 – aliakbarian

+0

真的很高興它的幫助。這確實只是一個問題正確的問題。在這個論壇上有很多知識,但新手往往無法獲取這些知識,因爲他們不知道該問什麼。 – john

+0

再次感謝你! :-) – aliakbarian

2

有一些相關的Q & A herehere值得一讀。

基本上你需要將字符串轉換爲通用格式 - 我的首選項總是轉換爲UTF-8,但是你的里程可能會有所警惕。

已經有大量的軟件做轉換寫入 - 轉換爲straigth前鋒,可以在幾個小時內寫的 - 但爲什麼不pick up something already done such as the UTF-8 CPP

+0

如果你只是Windows:http://msdn.microsoft.com/en-us/library/dd319072(v=VS.85).aspx。否則,請使用便攜式庫。 –

2

本頁面似乎也有用:http://www.codeproject.com/KB/string/UtfConverter.aspx

在該頁面的評論部分,也有這個任務像一些有趣的建議:

// Get en ASCII std::string from anywhere 
std::string sLogLevelA = "Hello ASCII-world!"; 

std::wstringstream ws; 
ws << sLogLevelA.c_str(); 
std::wstring sLogLevel = ws.str(); 

或者

// To std::string: 
str.assign(ws.begin(), ws.end()); 
// To std::wstring 
ws.assign(str.begin(), str.end()); 

雖然我不確定這些方法的有效性......

14

這是你如何與C++ 11做到這一點:

std::string str = "your string in utf8"; 
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>> converter; 
std::wstring wstr = converter.from_bytes(str); 

而這些都是你需要的標題:

#include <iostream> 
#include <string> 
#include <locale> 
#include <codecvt> 

一個更完整的例子可以在這裏找到: http://en.cppreference.com/w/cpp/locale/wstring_convert/from_bytes

+0

很好的答案,謝謝! ......但請按照cppreference.com上的示例進行操作。在Windows以外的操作系統上,'wchar_t'不是16位類型。您需要改用'char16_t'。 –

+0

@CrisLuengo謝謝!我更新了使用'char16_t'的答案。 –

+2

在lubuntu 16.04上不能使用g ++ 6.2或鏗鏘++ 3.8 – 2017-05-08 17:55:29

相關問題