2016-11-10 74 views
-1

我正在嘗試將代碼從VC++遷移到.net。 VC++代碼使用WinAPI提供的MultibyteToWideChar和WideCharToMultiByte函數。我嘗試在.NET中使用System.Text.Encoding類,但它不適用於所有編碼。有沒有其他的方式來做這種轉換?下面的代碼片段有什麼問題?.NET中MultibyteToWideChar和WideCharToMultiByte函數的替代方法是什麼?

這裏是我的C#代碼:

public static string MultiByteToWideChar(string input, int codepage) 
    { 
     Encoding e1 = Encoding.GetEncoding(codepage); 
     Encoding e2 = Encoding.Unicode; 

     //byte[] source = e1.GetBytes(input); 

     byte[] source = MBCSToByte(input); 

     byte[] target = Encoding.Convert(e1, e2, source); 

     return e2.GetString(target); 
    } 
public static string WideCharToMultiByte(string input, int codepage) 
    { 
     Encoding e1 = Encoding.Unicode; 
     Encoding e2 = Encoding.GetEncoding(codepage); 

     byte[] source = e1.GetBytes(input); 

     byte[] target = Encoding.Convert(e1, e2, source); 

     return Encoding.GetEncoding(codepage).GetString(target); 

    } 
private static byte[] MBCSToByte(string s) 
    { 
     byte[] b = new byte[s.Length]; 
     int i = 0; 
     foreach (char c in s) 
      b[i++] = (byte)c; 
     return b; 
    } 

的MultiByteToWideChar工作只爲代碼頁1255而不是866

調用WideCharToMultiByte是不工作的代碼頁1251

+1

什麼是不工作,你爲什麼要使用C++函數名的東西** **完全不同? 'Encoding'沒有問題。如果您使用正確的代碼頁,它可以將任何內容從一種編碼轉換爲另一種編碼。結束工作在其他功能上僅僅是保證你會得到轉換錯誤 –

+0

總結 - *什麼*你要轉換? 1255到Unicode? 1255至866?完全相同的代碼可以在任何情況下工作 –

+1

.NET字符串是Unicode * always *。你是否試圖修復一個損壞的字符串?沒有多字節或寬字符串。如果你想將一個字符串轉換爲一個1255字節數組只需使用'Encoging.GetEncoding(1255).GetBytes(someString);'。如果你想從1255陣列得到一個Unicode字符串,用'Encoging.GetEncoding(1255).GetString(someString);我正在寫' –

回答

1

MultiByteToWideChar()將編碼字節(非字符!)轉換爲Unicode字符。

WideCharToMultiByte() Unicode字符轉換到編碼的字節(不是字符!)。

在.NET中,string類型總是的Unicode字符序列(在UTF-16字節編碼)。所以使用string來保存編碼的字節是錯誤的。

在你MultiByteToWideChar()功能,你假設,輸入string包含的代碼頁的編碼8位字節的16位表示Unicode字符。您將Unicode字符原樣轉換爲byte[]陣列,然後將該(假定爲代碼頁編碼數組)轉換爲UTF-16 byte[]數組,然後將其轉換爲UTF-16 string。這將工作正常當且僅當最初的假設是真實的開始。通常情況並非如此,除非您的輸入已被破壞。

在你WideCharToMultiByte()功能,則在輸入string轉換爲UTF-16 byte[]陣列,那麼該陣列轉換成一個代碼頁編碼的byte[]陣列。到目前爲止好(雖然你可以只使用Encoding.GetBytes()從UTF-16 string去直接到代碼頁編碼byte[]不使用Encoding.Convert()在所有)。不過,你正在使用相同的代碼頁的代碼頁編碼byte[]數組轉換回UTF-16 string,因而未做你所做的一切。輸出string將是相同的值作爲輸入string(提供指定的代碼頁支持所有在輸入string中的Unicode字符的,否則就會在第一代碼頁轉換期間的數據丟失)。

話雖這麼說,正確的代碼應該看起來更像這個:

public static string MultiByteToWideChar(byte[] input, int codepage) 
    { 
     return Encoding.GetEncoding(codepage).GetString(input); 
    } 
public static byte[] WideCharToMultiByte(string input, int codepage) 
    { 
     return Encoding.GetEncoding(codepage).GetBytes(input); 
    } 

不要使用string舉行編碼字節,使用實際byte[]陣列代替。

+0

代碼是CLR存儲過程的一部分。我從SQL存儲過程傳入​​此CLR存儲過程的輸入。傳入的輸入類型是varchar和nvarchar。 SQL存儲過程應該做什麼來以字節數組而不是字符串形式傳入輸入。以下是正在調用多字節到unicode函數的sql代碼,並將unicode字節轉換爲out參數。 '聲明@input VARCHAR(2000) DECLARE @output VARBINARY(4000) DECLARE @outputup爲nvarchar(2000) 組@input = 'XXXXXXXXXXXXXXXXXXXXŽƒŽŠ€€ - ...‰'',€Z' EXEC cp2u @input,866 ,@output OUTPUT ' – Mahesh

+0

和預期輸出,這是「ОГОКАЗНАЧЕЙСТВАПО」 – Mahesh

+0

,你爲什麼和字符編碼處理手動呢?根據所涉及字段的聲明字符集和歸類,讓SQL數據庫爲您處理該數據庫。 –

1

string是一串字符,而不是一個字節流。當您將二進制數據封裝在string中時,您已經丟失了。

如果你想編碼之間的正確轉換,確保使用byte[]string已經給這些字節賦予了含義。 .NET的string與C的char*不一樣。保留stringstring s,並使用byte[]進行持久性,網絡連接等。

相關問題