2010-10-04 53 views
3

我剛剛絆倒了another question,其中有人建議使用new ASCIIEncoding().GetBytes(someString)從字符串轉換爲字節。對我來說,顯然它不適用於非ASCII字符。但事實證明,ASCIIEncoding愉快地用'?'代替無效字符。我對此很困惑,因爲這種打破最不讓人驚訝的規則。在Python中,它將是u"some unicode string".encode("ascii"),默認情況下轉換是嚴格的,因此在此示例中,非ASCII字符會導致異常。嚴格的字符串到C#中的字節編碼

兩個問題:

  1. 如何串嚴格轉換爲另一種編碼(如ASCII或Windows 1252),因此,如果出現無效字符拋出一個異常?順便說一下,我不希望foreach循環將每個Unicode數字轉換爲一個字節,然後檢查第8位。這應該是通過一個偉大的框架,如.NET(或Python ^^)來完成的。
  2. 關於此默認行爲背後的基本原理的任何想法?對我來說,默認情況下進行嚴格轉換更有意義,或者至少爲此目的定義一個參數(Python允許「替換」,「忽略」,「嚴格」)。

回答

7

.Net提供了在編碼轉換失敗時拋出異常的選項。您需要使用EncoderExceptionFallback類(如果輸入字符無法轉換爲編碼輸出字節序列),則創建編碼時會拋出EncoderFallbackException異常。下面的代碼是從那個類的文檔:

Encoding ae = Encoding.GetEncoding(
       "us-ascii", 
       new EncoderExceptionFallback(), 
       new DecoderExceptionFallback()); 

然後使用該編碼來執行轉換:

// The input string consists of the Unicode characters LEFT POINTING 
// DOUBLE ANGLE QUOTATION MARK (U+00AB), 'X' (U+0058), and RIGHT POINTING 
// DOUBLE ANGLE QUOTATION MARK (U+00BB). 
// The encoding can only encode characters in the US-ASCII range of U+0000 
// through U+007F. Consequently, the characters bracketing the 'X' character 
// cause an exception. 

string inputString = "\u00abX\u00bb"; 
byte[] encodedBytes = new byte[ae.GetMaxByteCount(inputString.Length)]; 
int numberOfEncodedBytes = 0; 
try 
{ 
    numberOfEncodedBytes = ae.GetBytes(inputString, 0, inputString.Length, 
             encodedBytes, 0); 
} 
catch (EncoderFallbackException e) 
{ 
    Console.WriteLine("bad conversion"); 
} 

MSDN page, "Character Encoding in the .NET Framework"討論,在一定程度上,後面的默認轉換行爲的理由。總之,他們不想幹擾依賴於此行爲的傳統應用程序。不過,他們建議覆蓋默認值。

+0

很好的解釋。我曾看到過這樣一句話:「您可能想考慮讓應用程序將EncoderFallback或DecoderFallback設置爲EncoderExceptionFallback或DecoderExceptionFallback,以防止設置了第8位的序列。」在文檔中,但對我來說這並不明顯,它可以用於嚴格的轉換。 – AndiDog 2010-10-04 22:12:09