2015-05-12 1 views
1

Рассмотрим следующий код С #В чем разница между выходными шестнадцатеричными байтами с использованием различных типов схем кодирования в C#?

 int x = 126; 
    string s = "126"; 
    FileStream fs = new FileStream("test.txt", FileMode.Create); 
    StreamWriter sw = new StreamWriter(fs); 
    sw.WriteLine(x); 
    sw.WriteLine(s); 

Выход (в шестнадцатеричной байт хранится в test.txt) 31 32 36 0D 0A 31 32 36 0D 0A

Если я внести изменения в строке 4:

StreamWriter sw = new StreamWriter(fs, Encoding.Unicode); 

выход: FF FE 31 00 32 00 36 00 0D 00 0A 31 00 00 32 00 36 00 0D 00 0A 00

Может кто-нибудь помочь мне с логикой. Есть ли ссылки на различные схемы кодирования и их поведение с файловыми системами с использованием C#

+0

Если вас интересует, почему 'int' и' string' закодированы в один и тот же гекс, 'StreamWriter' записывает как строку. Попробуйте 'BinaryWriter' увидеть разницу – Orifjon

ответ

5

Предлагаю вам прочитать Joel Spolsky's excellent article on the subject of character sets and encodings. Короче говоря:

  • Файл представляет собой всего лишь последовательность байтов.
  • Строка представляет собой последовательность символов.
  • набор символов определяет набор символов и assignes уникальный код точку (целое число, представляющее символ - обратите внимание, что «целое число» не обязательно является int) к каждому символу.
  • Если вы хотите сохранить строку в файле, вам необходимо преобразовать последовательность символов в последовательность байтов. Для наборов символов с 256 символами или менее обычно существует взаимно однозначное соответствие между символами и байтами, но для больших наборов символов, таких как Unicode, оно становится более сложным.
  • Кодировка определяет, как коды символов для символов строки должны быть переведены в байты.

Таким образом, при изменении кодировки одна и та же строка преобразуется в другую последовательность байтов.

Обратите внимание, что поведение наборов символов и кодировок не зависит от языка программирования. Что такое изменения, как вы относитесь к различным кодировкам и наборам символов и используете их (как правило, кодировка привязана к определенному набору символов, поэтому выбор кодировки также неявно выбирает набор символов). В случае с C# Encoding.Unicode плохо назван - это набор символов Unicode , но кодировка UTF-16LE (в которой каждый второй байт будет 00, если вы используете только английские символы).

Кроме того, обратите внимание, что строки представлены как char массивов внутренне в программе, где каждый char представляет собой значение, которое представляет собой две последующих байты из UTF-16 кодировки (так что некоторые фантазии персонажей действительно могут быть представлены в виде два char значений) , Вы не можете получить доступ к этому массиву напрямую, и большая часть функциональности строки пытается абстрагировать этот факт. Это внутреннее кодирование не влияет на то, как строки записываются в файлы (либо вы выбираете кодировку вручную, либо получаете набор символов по умолчанию, который вы вызываете), что для StreamWriter является UTF-8 (благодаря @xanatos для коррекция)).

+0

Абсолютно совершенный ...существует даже разница между набором символов и кодировкой набора символов (unicode и utf-X) ... только одно: * целое число, которое представляет символ *, было бы лучше использовать слово * number *, потому что целое слишком похоже на 'int' – xanatos

+1

@xanatos: Спасибо! Это вопрос, который заставил меня ударить 20 000 точек репутации, поэтому я добавил в него дополнительные усилия ;-) Я думаю, что «число» слишком общее, но я добавил объяснение, что я не имею в виду «int». –

+1

'StreamWriter' по умолчанию использует UTF8, поэтому * или вы получаете набор символов по умолчанию для операционной системы *, по крайней мере, ложно по сравнению с вопросом. Существует даже небольшая неточность: вы используете дважды 'UTF-16', но Encoding.Unicode -' UTF16-LE' (как написано [здесь] (https://msdn.microsoft.com/en-us/library/system .text.encoding.unicode.aspx)), в то время как C# /. NET-кодировка, вероятно, UTF16 (текущая платформа) (например, XBox360 - Big Endian) – xanatos

Смежные вопросы