2012-05-23 14 views
1

我試圖unicode字符串從.NET到本地C++來轉換,這樣我可以把它們寫入到一個文本文件中。該過程將被顛倒過來,以便讀取文件中的文本並將其轉換爲受管unicode字符串。統一<->多字節轉換(Native對管理)

我使用下面的代碼:

String^ FromNativeToDotNet(std::string value) 
{ 
    // Convert an ASCII string to a Unicode String 
    std::wstring wstrTo; 
    wchar_t *wszTo = new wchar_t[lvalue.length() + 1]; 
    wszTo[lvalue.size()] = L'\0'; 
    MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, wszTo, (int)value.length()); 
    wstrTo = wszTo; 
    delete[] wszTo; 

    return gcnew String(wstrTo.c_str()); 
} 


std::string FromDotNetToNative(String^ value) 
{ 
    // Pass on changes to native part 
    pin_ptr<const wchar_t> wcValue = SafePtrToStringChars(value); 
    std::wstring wsValue(wcValue); 

    // Convert a Unicode string to an ASCII string 
    std::string strTo; 
    char *szTo = new char[wsValue.length() + 1]; 
    szTo[wsValue.size()] = '\0'; 
    WideCharToMultiByte(CP_UTF8, 0, wsValue.c_str(), -1, szTo, (int)wsValue.length(), NULL, NULL); 
    strTo = szTo; 
    delete[] szTo; 

    return strTo; 
} 

什麼情況是,例如一個日文字符被轉換爲兩個ASCII字符(漢 - >「w)。我認爲這是正確的? 但另一種方式不起作用:當我打電話給FromNativeToDotNet wizh」w我只能得到「w作爲託管unicode字符串.. 如何正確恢復日文字符?

回答

1

試試這個:

String^ FromNativeToDotNet(std::string value) 
{ 
    // Convert a UTF-8 string to a UTF-16 String 
    int len = MultiByteToWideChar(CP_UTF8, 0, value.c_str(), value.length(), NULL, 0); 
    if (len > 0) 
    { 
    std::vector<wchar_t> wszTo(len); 
    MultiByteToWideChar(CP_UTF8, 0, value.c_str(), value.length(), &wszTo[0], len); 
    return gcnew String(&wszTo[0], 0, len); 
    } 

    return gcnew String((wchar_t*)NULL); 
} 

std::string FromDotNetToNative(String^ value) 
{ 
    // Pass on changes to native part 
    pin_ptr<const wchar_t> wcValue = SafePtrToStringChars(value); 

    // Convert a UTF-16 string to a UTF-8 string 
    int len = WideCharToMultiByte(CP_UTF8, 0, wcValue, str->Length, NULL, 0, NULL, NULL); 
    if (len > 0) 
    { 
    std::vector<char> szTo(len); 
    WideCharToMultiByte(CP_UTF8, 0, wcValue, str->Length, &szTo[0], len, NULL, NULL); 
    return std::string(&szTo[0], len); 
    } 

    return std::string(); 
} 
+0

不能從Unicode轉換爲UTF-8,因爲UTF-8是Unicode的已! – tchrist

+0

語義。 Windows和.NET使用UTF-16作爲Unicode字符串的編碼。我相應地更改了我的答案中的註釋,但代碼保持不變。 –

+0

Unicode標準實際上定義了這些條款。微軟不能自由地接受,擴展,修飾和消除公認的國際標準中爲其自身惡意目的而精心定義的術語。充其量,它傳播不準確和混亂。在中間,這是一個謊言。我不知道最糟糕的是什麼,因爲微軟夢寐以求的壟斷計劃遠遠超出了我自己的想象。這些詞有標準的含義;我強烈建議你使用它們。 – tchrist

2

將日文字符轉換爲兩個ASCII字符(漢 - >「w)。我認爲這是正確的?

否,該字符,U + 6F22,應轉換爲三個字節:0xE6 0xBC 0xA2

在UTF-16(小端)U + 6F22被存儲在存儲器中作爲爲0x22 0x6F,這將看起來像ASCII "o(而不是"w),所以它看起來像什麼是錯的與你從字符串轉換到^的std :: string。

我不熟悉字符串^知道從String ^轉換爲std :: wstring的正確方法,但我很確定這是您的問題所在。


我不認爲下面有什麼與你的問題,但它顯然是錯誤的:

std::string strTo; 
char *szTo = new char[wsValue.length() + 1]; 

你已經知道了一個寬字符可以產生多個窄字符,所以寬字符的數量顯然不一定等於或大於對應的窄字符的數量。

您需要使用調用WideCharToMultiByte來計算緩衝區大小,然後用該大小的緩衝區再次調用它。或者你可以分配一個緩衝區來保存3倍的字符數作爲寬字符。

3

最好使用UTF8Encoding:

static String^ FromNativeToDotNet(std::string value) 
{ 
    array<Byte>^ bytes = gcnew array<Byte>(value.length()); 
    System::Runtime::InteropServices::Marshal::Copy(IntPtr((void*)value.c_str()), bytes, 0, value.length()); 
    return (gcnew System::Text::UTF8Encoding)->GetString(bytes); 
} 


static std::string FromDotNetToNative(String^ value) 
{ 
    if (value->Length == 0) return std::string(""); 
    array<Byte>^ bytes = (gcnew System::Text::UTF8Encoding)->GetBytes(value); 
    pin_ptr<Byte> chars = &bytes[0]; 
    return std::string((char*)chars, bytes->Length); 
} 
+0

這應該被標記爲正確的答案。比公認的答案簡單得多。 –

相關問題