2016-10-29 3 views
3

主な理由は、ソケット上でUnicodeデータ(バイトではなく文字ではない)を送信していて、wchar_tがUTF16であるためエンディアンが一致するようにしたいからです。C++ - wchar_tをネットワークバイトとバックに変換する

また、受信プログラムは私のもう1つのプログラムなので、それがUTF16であり、それに応じて対応できることがわかります。

ここに私の現在のアルゴリズムは動作していますが、奇妙な結果があります。完全に異なる方法で

쳌쳌쳌쳌쳌곭쳌쳌쳌쳌쳌ē쳌쳌쳌쳌This is a string 
+0

のwcharはUTF16ではありません(http://stackoverflow.com/questions/16050218/utf8-vs-wide-char)[この記事を読む]広いcharactereです。それは何でもかまいません。 – Stargateur

+0

私の悪い、私はwchar_t/unicode/charについて話しているスレッドを間違って読まなければならない。しかし、はい、あなたは正しいです。 (私はそれがデフォルトではMSVCコンパイラのUTF16だと聞きましたが) –

+0

C++での型打ちはUBです。私はあなたがDataAでやっていることをあなたが許可されているとは思わない。 – Asu

答えて

3

UTF8とUTF16ストアテキスト:

case WM_CREATE: { 


    //Convert String to NetworkByte 
    wchar_t Data[] = L"This is a string"; 
    char* DataA = (char*)Data; 
    unsigned short uData = htons((unsigned int)DataA); 

    //Convert String to HostByte 
    unsigned short hData = ntohs(uData); 
    DataA = (char*)&hData; 
    wchar_t* DataW = (wchar_t*)DataA; 
    MessageBeep(0); 


    break; 
} 

結果(私はそれを送信する前にそれを変換する方法を学習したかったので、これは、同じアプリケーションです) 。 wchar_t*char*の鋳造は無意味です。鋳造と同じです。floatchar*です。

WideCharToMultiByteを使用して、UTF16をUTF8に変換してネットワーク機能に送信します。

ネットワーク機能からUTF8を受信する場合は、Windows機能で使用できるように、MultiByteToWideCharを使用してUTF16に変換し直してください。

例:

#include <iostream> 
#include <string> 
#include <windows.h> 

std::string get_utf8(const std::wstring &wstr) 
{ 
    if (wstr.empty()) return std::string(); 
    int sz = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], -1, 0, 0, 0, 0); 
    std::string res(sz, 0); 
    WideCharToMultiByte(CP_UTF8, 0, &wstr[0], -1, &res[0], sz, 0, 0); 
    return res; 
} 

std::wstring get_utf16(const std::string &str) 
{ 
    if (str.empty()) return std::wstring(); 
    int sz = MultiByteToWideChar(CP_UTF8, 0, &str[0], -1, 0, 0); 
    std::wstring res(sz, 0); 
    MultiByteToWideChar(CP_UTF8, 0, &str[0], -1, &res[0], sz); 
    return res; 
} 

int main() 
{ 
    std::wstring greek = L"ελληνικά"; 

    std::string utf8 = get_utf8(greek); 
    //use utf8.data() for network function... 

    //convert utf8 back to utf16 so it can be displayed in Windows: 
    std::wstring utf16 = get_utf16(utf8); 
    MessageBoxW(0, utf16.c_str(), 0, 0); 

    return 0; 
} 


編集

UTF16とUTF8の違いを示すためのもう一つの例。この例では、UTF16とUTF8のバイト値を調べます。

ラテンアルファベットの場合、UTF8とANSIバイトはまったく同じです。

また、ラテンアルファベットには、UTF16とUTF16の間に類似点がありますが、UTF16には余分なゼロがあります。

ギリシャ語と中国語アルファベットには大きな違いがあります。

//(Windows example) 
void printbytes_char(const char* ANSI_or_UTF8) 
{ 
    const char *bytes = ANSI_or_UTF8; 
    int len = strlen(bytes); 
    for (size_t i = 0; i < len; i++) 
     printf("%02X ", 0xFF & bytes[i]); 
    printf("\n"); 
} 

void printbytes_wchar_t(const wchar_t* UTF16) 
{ 
    //Note, in Windows wchar_t length is 2 bytes 
    const char *bytes = (const char*)UTF16; 
    int len = wcslen(UTF16) * 2; 
    for (size_t i = 0; i < len; i++) 
     printf("%02X ", 0xFF & bytes[i]); 
    printf("\n"); 
} 

int main() 
{ 
    printbytes_char("ABC"); 
    printbytes_char(u8"ABC"); 
    printbytes_wchar_t(L"ABC"); 

    printbytes_char(u8"ελληνικά"); 
    printbytes_wchar_t(L"ελληνικά"); 

    printbytes_char(u8"汉字/漢字"); 
    printbytes_wchar_t(L"汉字/漢字"); 
    return 0; 
} 

出力:

"ABC": 
41 42 43 //ANSI 
41 42 43 //UTF8 
41 00 42 00 43 00 //UTF16 (this is little endian, bytes are swapped) 

"ελληνικά" 
CE B5 CE BB CE BB CE B7 CE BD CE B9 CE BA CE AC //UTF8 
B5 03 BB 03 BB 03 B7 03 BD 03 B9 03 BA 03 AC 03 //UTF16 

"汉字/漢字" 
E6 B1 89 E5 AD 97 2F E6 BC A2 E5 AD 97 //UTF8 
49 6C 57 5B 2F 00 22 6F 57 5B //UTF16 
+1

あなたの解決策はWindows上でのみ動作します – Stargateur

+0

@Stargateurはい、Windows固有です。 OPは 'winsock 'とタグ付けした。 UnixベースのシステムではUTF8をどこでも使用しているため、このような変換は不要です。 –

+0

私はMessageBoxWがユニコードを扱うので、それは仕事だと思います。コンソールでwprintfまたはstd :: coutを試してみてください。 [MessageBoxW(Unicode)およびMessageBoxA(ANSI)](https://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx) – Stargateur

0
wchar_t Data[] = L"test"; 

    //Convert String to NetworkByte 
    for (wchar_t &val : Data) { 
     if (sizeof(val) == 4) { 
      val = htonl(val); 
     } 
     else if (sizeof(val) == 2) { 
      val = htons(val); 
     } 
     else { 
      static_assert(sizeof(val) <= 4, "wchar_t is gretter that 32 bit"); 
     } 
    } 

    //Convert String to HostByte 
    for (wchar_t &val : Data) { 
     if (sizeof(val) == 4) { 
      val = ntohl(val); 
     } 
     else if (sizeof(val) == 2) { 
      val = ntohs(val); 

     } 
     else { 
      static_assert(sizeof(val) <= 4, "wchar_t is gretter that 32 bit"); 
     } 
    } 
+0

できません。キャストは間違っています。ラテン語ではない言語で試してみましょう。 –

+0

@BarmakShemirani htonsとntohは32ビット以下のすべての型で動作する必要があるので、確かですか? wchar_tは32bit maxではないと思われますか? – Stargateur

+0

@BarmakShemirani You right – Stargateur

関連する問題