2010-10-04 16 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