2012-04-23 127 views
3

我面臨着非常奇怪的問題,其中我有byte [],當我傳遞給Convert.UTF8.GetString(byte [] bytes)方法時,系統編碼是搞亂了我的字節,只用幾個特殊的字節(我在系統中用作標記)替換爲三個char字符串表示形式。C#Encoding.UTF8弄亂了字節[]

[0] 70 byte 
[1] 49 byte 
[2] 45 byte 
[3] 86 byte 
[4] 49 byte 
[5] 253 byte  <-- Special byte 
[6] 70 byte 
[7] 49 byte 
[8] 45 byte 
[9] 86 byte 
[10]50 byte 
[11]253 byte  <-- Special byte 
[12]70 byte 
[13]49 byte 
[14]45 byte 
[15]86 byte 
[16]51 byte 

當我通過上面byte []到Encoding.UTF8.GetString(字節)的方法我得到以下輸出;

​​

實際值不應該有' ',因爲這意味着它沒有編碼並用' '代替這些特殊字節。無論如何,我可以解決這個問題,即轉換爲字符串並將特殊字節表示保留爲單個字符。

我有以下特殊字節,我試圖用作標記;

byte AM = (byte) 254 
byte VM = (byte) 253 
byte SM = (byte) 252 

您的幫助和意見將不勝感激。

感謝,

-

Sheeraz

回答

2

的數據是隻有UTF-8 之間的標記,所以如果是我我將提取分隔部第一,然後UTF-8解碼每個部分單獨地,即,通過byte[]尋找讀你的二進制數據中的標記,給你3個二進制塊(70,49,45,86,49; 70,49,45,86,50; 70,59,45,86,51),然後將它們解碼成3串。你不能UTF-8解碼整個二進制序列,因爲它不是有效的UTF-8

但是,個人而言,我會說在這裏使用分隔符是危險的;我可能會去一個長度前綴的方法,使

  • 我知道我不小心混爲一談分隔符和
  • 我可以更有效地處理比逐字節
真實數據

例如,如果我們使用了「varint」長度的前綴,這將是:

05,70,49,45,86,49,05,70,49,45,86,50,05,70,59,45,86,51 

其中05是「varint」長度,我們解釋爲5個字節;這意味着我們可以很好地處理:

// pseude code 
while(!EOF) { 
    int len = ReadVarint(); 
    var blob = ReadBytes(len); 
    string s = Utf8Decode(blob); 
    // ... 
} 
+0

謝謝...我必須手動完成它,因爲要求是將UTF-8編碼的所有內容都編碼爲我的數據庫僅爲UTF-8。我現在我沒有將任何東西轉換成字符串,但只處理字節。 – SJunejo 2012-04-24 22:27:47

+0

@SJunejo k,但請注意:您目前的策略**不是UTF-8 **。您的數據庫將完全處於您的權利爆炸範圍之內。 – 2012-04-24 22:30:24

7

不能使用這些特殊值作爲一個UTF-8字符串中的標記,因爲字符串結束根據UTF-8 encoding rules是無效。

可以偷偷插入他們,然後帶他們回來了之前的數據被送到UTF-8數據的相關代碼一樣Encoding.GetString,但因爲它是偷偷摸摸不是一個好主意,正好混亂到(方式任何人都不知道在那裏發生了什麼伏都教,因此非常不利於生產)。

更理智的選擇是在您的字符串中插入「特殊」的UTF-8編碼字符。這在技術上要求(特別是如果你選擇一個字符編碼爲1字節,因爲那些更有可能發生在你的實際有效載荷內),你也想出了一個方案轉義這些字符當它們自然發生時你的有效載荷

+0

+1如果您需要這樣的標記,那麼您可以在Unicode內的某處選擇一個字符來代替,例如,在其中一個專用範圍內,然後使用這些字符的有效UTF-8編碼作爲標記。但是它們每個都會超過一個字節。或者提前在您的標記周圍切掉字節流,然後將每個有效部分轉換爲Unicode,但是您需要小心,不要真正使用這些字節來獲取真正的UTF-8編碼 - 即,您會有效地正在編寫你自己的解碼器。 – Rup 2012-04-23 10:13:21