Какую кодировку использовать для чтения строки из файла?

Я анализирую файл (который я не генерирую), который содержит строку. Строка всегда предшествует 2 байта, которые говорят мне длину строки, которая следует.

Например:

05 00 53 70 6F 72 74

было бы:

Sport

Используя C# BinaryReader, я читаю строку, используя:

string s = new string(binaryReader.ReadChars(size));

Иногда есть странный характер, который, кажется, продвигает позицию потока дальше, чем следовало бы. Например:

0D 00 63 6F 6F 6B 20 E2 80 94 20 62 6F 6F 6B

Должно быть:

cook - book

и хотя он хорошо читается, поток заканчивается на два байта дальше, чем должен?! (Который тогда портит остальную часть анализа.)

Я предполагаю, что это как-то связано с 0xE2 посередине, но я не совсем уверен, почему или как с этим бороться.

Любые предложения с благодарностью!

3 ответа

Решение

Я предполагаю, что строка закодирована в UTF-8. 3-байтовая последовательность E2 80 94 соответствует одному символу Unicode U+2014 (EM DASH).

В вашем первом примере

05 00 53 70 6F 72 74

ни один из байтов не превышает 0x7F, и это является пределом для 7-битного ASCII. UTF-8 сохраняет совместимость с ASCII, используя 8-й бит, чтобы указать, что будет больше информации.

0D 00 63 6F 6F 6B 20 E2 80 94 20 62 6F 6F 6B

Тед заметил, что ваши "проблемы" начинаются с 0xE2, потому что это не 7-битный символ ASCII.

Первый байт 0x0D говорит нам, что должно быть 11 символов, но есть 13 байтов.

0xE2 говорит нам, что мы нашли начало последовательности UTF-8, так как установлен самый старший бит (больше 127). В этом случае последовательность, которая представляет - (EM Dash).

Как вы правильно сказали, проблема в символе E2. BinaryReader.ReadChars(n) не читает n-байтов, но n символов Unicode в кодировке UTF-8. Смотрите Википедию для кодировки Unicode. Термин, который вы используете, - это суррогатные персонажи. В UTF-8 символы в диапазоне от 000080 до 00009F представлены двумя байтами. Это причина вашего несоответствия смещения.

Вам нужно использовать BinaryReader.ReadBytes, чтобы исправить проблему смещения и передать ее в экземпляр Encoding.

Чтобы это работало, вам нужно прочитать байты с помощью BinaryReader, а затем декодировать его с правильной кодировкой. Предполагая, что вы имеете дело с UTF-8, вам нужно передать байтовый массив

Encoding.UTF8.GetString(byte [] rawData)

чтобы вернуть правильно закодированную строку.

С уважением, Алоис Краус

Другие вопросы по тегам