Разница в написании строки по сравнению с массивом символов с помощью System.IO.BinaryWriter - PullRequest
4 голосов
/ 18 июня 2009

Я пишу текст в двоичный файл на C # и вижу разницу в количестве, записанном между записью строки и массива символов. Я использую System.IO.BinaryWriter и смотрю BinaryWriter.BaseStream.Length, когда происходит запись. Вот мои результаты:

using(BinaryWriter bw = new BinaryWriter(File.Open(“data.dat”), Encoding.ASCII))
{
  string value = “Foo”;

  // Writes 4 bytes
  bw.Write(value);

  // Writes 3 bytes 
  bw.Write(value.ToCharArray());
}

Я не понимаю, почему перегрузка строки записывает 4 байта, когда я пишу только 3 символа ASCII. Кто-нибудь может объяснить это?

Ответы [ 4 ]

13 голосов
/ 18 июня 2009

В документации для BinaryWriter.Write(string) указано, что в этот поток записывается строка с префиксом длины. Перегрузка для Write(char[]) не имеет такого префикса.

Мне кажется, что дополнительные данные - это длина.

EDIT:

Просто для большей ясности используйте Reflector. Вы увидите, что в нем есть этот фрагмент кода как часть Write(string) метода:

this.Write7BitEncodedInt(byteCount);

Это способ кодировать целое число, используя наименьшее возможное количество байтов. Для коротких строк (которые мы будем использовать изо дня в день, длиной не более 128 символов), он может быть представлен одним байтом. Для более длинных строк он начинает использовать больше байтов.

Вот код этой функции на тот случай, если вы заинтересованы:

protected void Write7BitEncodedInt(int value)
{
    uint num = (uint) value;
    while (num >= 0x80)
    {
        this.Write((byte) (num | 0x80));
        num = num >> 7;
    }
    this.Write((byte) num);
}

После добавления префикса длины в этой кодировке он записывает байты для символов в нужной кодировке.

5 голосов
/ 18 июня 2009

Из BinaryWriter.Write(string) документов :

Записывает строку с префиксом длины *1007* в этот поток в текущей кодировке BinaryWriter и продвигает текущую позицию потока в соответствии с используемой кодировкой и конкретными символами, записываемыми в поток.

Такое поведение, вероятно, таково, что при чтении файла обратно с использованием BinaryReader можно идентифицировать строку. (Например, 3Foo3Bar6Foobar может быть проанализирован в строку "Foo", "Bar" и "Foobar", но FooBarFoobar не может быть.) Фактически, BinaryReader.ReadString использует именно эту информацию для чтения string из двоичного файла файл.

Из BinaryWriter.Write(char[]) документов :

Записывает массив символов в текущий поток и увеличивает текущую позицию потока в соответствии с используемой кодировкой и конкретными символами, записываемыми в поток.

Трудно переоценить, насколько исчерпывающими и полезными являются документы по MSDN. Всегда проверяйте их в первую очередь.

1 голос
/ 18 июня 2009

Как уже говорилось, BinaryWriter.Write (String) записывает длину строки в поток перед записью самой строки.

Это позволяет BinaryReader.ReadString () знать, какова длина строки.

using (BinaryReader br = new BinaryReader(File.OpenRead("data.dat")))
{
    string foo1 = br.ReadString();
    char[] foo2 = br.ReadChars(3);
}
0 голосов
/ 18 июня 2009

Вы смотрели на то, что на самом деле было написано? Я предполагаю, что нулевой терминатор.

...