Вопрос по c# – Кодировка, используемая в приведении от символа к байту

7

Посмотрите на следующий код C # (функция извлечена изBuildProtectedURLWithValidity функция вhttp: //wmsauth.org/example):

byte[] StringToBytesToBeHashed(string to_be_hashed) {
    byte[] to_be_hashed_byte_array = new byte[to_be_hashed.Length];
    int i = 0;
    foreach (char cur_char in to_be_hashed)
    {
        to_be_hashed_byte_array[i++] = (byte)cur_char;
    }
    return to_be_hashed_byte_array;
}

Мой вопрос: Что происходит с преобразованием байта в символ с точки зрения кодирования?

Я полагаю, что на самом деле ничего не происходит с точки зрения кодирования, но означает ли это, что используется именно Encoding.Default, и поэтому возвращаемый байт будет зависеть от того, как инфраструктура будет кодировать базовую строку в конкретной Оперативной системе?

И кроме того, действительно ли символ больше байта (я предполагаю 2 байта) и пропустит первый байт?

Я думал заменить все это на:

Encoding.UTF8.GetBytes(stringToBeHashed)

Что вы думаете

Ваш Ответ

3   ответа
15

. и строк. Целочисленное значение символа (которое можно получить, приведя кint) эквивалентен его единице кода UTF-16. Для символов в базовой многоязычной плоскости (которые составляют большинство символов, с которыми вы когда-либо сталкивались) это значение - кодовая точка Unicode.

.NET Framework используетChar структура для представления символа Unicode. Стандарт Unicode идентифицирует каждый символ Unicode с помощью уникального 21-битного скалярного числа, называемого кодовой точкой, и определяет форму кодирования UTF-16, которая определяет, как кодовая точка кодируется в последовательность из одного или нескольких 16-битных значений. Каждое 16-битное значение варьируется от шестнадцатеричного0x0000 через0xFFFF и хранится вChar состав. ЗначениеChar объект - это его 16-разрядное числовое (порядковое) значение. -Char Structure

Кастингchar вbyte приведет к потере данных для любого символа, значение которого больше 255. Попробуйте выполнить следующий простой пример, чтобы понять, почему:

char c1 = 'D';        // code point 68
byte b1 = (byte)c1;   // b1 is 68

char c2 = 'ń';        // code point 324
byte b2 = (byte)c2;   // b2 is 68 too!
                      // 324 % 256 == 68

Да, тебе обязательно стоит использоватьEncoding.UTF8.GetBytes вместо.

4

byte а такжеchar похоже на использование ISO-8859-1 encoding (= первые 256 символов Unicode), за исключением того, что он молча теряет информацию при кодировании символов за пределами U + 00FF.

И кроме того, действительно ли символ больше байта (я предполагаю 2 байта) и пропустит первый байт?

Да. A C #char = Кодовая единица UTF-16 = 2 байта.

1

char представляет 16-битную кодовую точку UTF-16. Кастингchar вbyte приводит к младшему байту символа, но обаДугла а также Dan04 ошибаются в том, что всегда будут тихо сбрасывать старший байт. Если старший байт не равен нулю, результат зависит от того, включена ли опция компилятора Проверьте наличие арифметического переполнения / недостаточного значения установлено:

namespace CharTest
{
    class Program
    {
        public static void Main(string[] args)
        {   ByteToCharTest( 's' );
            ByteToCharTest( 'ы' );

            Console.ReadLine();
        }

        static void ByteToCharTest( char c )
        {   const string MsgTemplate =
                "Casting to byte character # {0}: {1}";

            string msgRes;
            byte   b;

            msgRes = "Success";
            try
            {   b = ( byte )c;  }
            catch( Exception e )
            {   msgRes = e.Message;  }

            Console.WriteLine(
                String.Format( MsgTemplate, (Int16)c, msgRes ) );
        }
    }
}

Выход с проверкой переполнения:

Casting to byte character # 115: Success
Casting to byte character # 1099: Arithmetic operation resulted in an overflow.

Выход без проверки переполнения:

Casting to byte character # 115: Success        
Casting to byte character # 1099: Success
Может быть, в какой-то странной среде это бросает, но я думаю, что в большинстве сред этот случай не бросает. Я проверил в своем локальном «Microsoft (R) Visual C # Compiler версии 4.6.1590.0» и в repl.it: Repl.it / Irlw / 1 И оба возвращают успех в обоих случаях (без исключений, как показывает ваш вывод). Mariano Desanze
@ Mariano Desanze, я не могу рассказать о Mono, но как MS может конвертировать его без ошибок, если их собственный справочный источник ясно показывает, что входной символ являетсяв сравнени (в строке 725) доByte.MaxValue перед преобразованием, и возникает исключение, если значение символа не помещается в байт? Мое окружение не странное - это просто ванильное .NET 3.5. Тихая отбрасывание старшего байта - плохая иде Ant_222
Понял: у меня был Проверьте наличие арифметического переполнения / недостаточного значенияпция @ включена в SharpDevelop. Таким образом, результат этого преобразования амбивалентен, то есть зависит от настроек компилятора! Ant_222
В таком случае извините за понижение голосов. Я верну его, если вы отредактируете свой ответ, поскольку я не могу иначе (возможно, вы можете уточнить, что он не будет действовать в каждой среде). Но это действительно странно, потому что даже на онлайн-переводчике на Microsoft.com / нетто ты можешь поставитьchar c = 'ы'; Console.WriteLine((byte)c); и увидите, что вместо исключения получается «75». Mariano Desanze
Я отредактировал ответ - спасибо за отзыв. Похоже, проверка переполнения отключена по умолчанию. Ant_222

Похожие вопросы