Строгое кодирование байтов в C # - PullRequest
3 голосов
/ 05 октября 2010

Я только что наткнулся на другой вопрос , в котором кто-то предложил использовать new ASCIIEncoding().GetBytes(someString) для преобразования строки в байты. Для меня было очевидно, что это не должно работать для не-ASCII символов. Но, как оказалось, ASCIIEncoding с радостью заменяет недопустимые символы на «?». Я очень смущен этим, потому что этот вид нарушает правило наименьшего удивления. В Python это будет u"some unicode string".encode("ascii"), и преобразование является строгим по умолчанию, так что символы, отличные от ASCII, приведут к исключению в этом примере.

Два вопроса:

  1. Как можно строго преобразовать строки в другую кодировку (например, ASCII или Windows-1252), чтобы при возникновении недопустимых символов возникало исключение? Кстати, я не хочу, чтобы цикл foreach преобразовывал каждое число Unicode в байт, а затем проверял 8-й бит. Предполагается, что это должно быть сделано с помощью замечательного фреймворка, такого как .NET (или Python ^^).
  2. Есть какие-нибудь идеи по поводу этого поведения по умолчанию? Для меня имеет больше смысла делать строгие преобразования по умолчанию или, по крайней мере, определять параметр для этой цели (Python позволяет «заменить», «игнорировать», «строгий»).

1 Ответ

7 голосов
/ 05 октября 2010

.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 "Кодировка символов в .NET Framework" в некоторой степени обсуждается обоснование поведения преобразования по умолчанию. Таким образом, они не хотели беспокоить устаревшие приложения, которые зависят от этого поведения. Тем не менее, они рекомендуют переопределить значение по умолчанию.

...