Подтвердить что ты не робот

Почему BinaryWriter добавляет тарабарщину к началу потока? Как вы его избегаете?

Я отлаживаю некоторые проблемы с написанием фрагментов объекта в файл, и я перешел к основному случаю, только открыв файл и набрав в нем "TEST". Я делаю это следующим образом:

static FileStream fs;
static BinaryWriter w;
fs = new FileStream(filename, FileMode.Create);
w = new BinaryWriter(fs);

w.Write("test");

w.Close();
fs.Close();

К сожалению, это заканчивается тем, что добавляет поле к фронту файла и выглядит так:

ТЕСТ, с футбольным полем спереди. Почему это и как я могу избежать этого?

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

4b9b3361

Ответ 1

Они не являются байтами байтов, а префикс длины, согласно MSDN:

public virtual void Write(string value);

Записывает строку с префиксом длины в [the] stream

И вам понадобится этот префикс длины, если вы когда-нибудь захотите прочитать строку с этой точки. См. BinaryReader.ReadString().

Дополнительные

Так как вам кажется, что вы действительно хотите проверить файл-заголовок

  • Это проблема? Вы читаете префикс длины назад, чтобы проверить тип файла, который он работает.

  • Вы можете преобразовать строку в массив byte [], возможно используя Encoding.ASCII. Но вы должны либо использовать фиксированную (подразумеваемую) длину, либо... префикс ее самостоятельно. После чтения байта [] вы можете снова преобразовать его в строку.

  • Если у вас было много текста для записи, вы могли бы даже привязать TextWriter к тому же потоку. Но будьте осторожны, писатели хотят закрыть свои потоки. Я бы не советовал это вообще, но это хорошо знать. Здесь также вам нужно будет отметить точку, в которой может перейти другой читатель (фиксированный заголовок работает нормально).

Ответ 2

Байт в начале - это длина строки, которая выписывается как целое число переменной длины.

Если строка содержит 127 символов или меньше, длина будет сохранена как один байт. Когда строка достигает 128 символов, длина записывается как 2, и она также будет перемещаться на 3 и 4 на некоторых длинах.

Проблема заключается в том, что вы используете BinaryWriter, который записывает данные, которые BinaryReader может прочитать позже. Если вы хотите записать свой собственный собственный формат, вы должны либо отказаться от записи таких строк, либо вообще отказаться от использования BinaryWriter.

Ответ 3

Это потому, что BinaryWriter записывает двоичное представление строки, включая длину строки. Если вы должны были писать прямые данные (например, byte [] и т.д.), Он не будет включать эту длину.

byte[] text = System.Text.Encoding.Unicode.GetBytes("test");
FileStream fs = new FileStream("C:\\test.txt", FileMode.Create);
BinaryWriter writer = new BinaryWriter(fs);
writer.Write(text);
writer.Close();

Вы заметите, что он не включает длину. Если вы собираетесь писать текстовые данные с помощью двоичного писателя, сначала вам нужно его преобразовать.

Ответ 4

Как отметил Хенк в этом ответе, это длина строки (в виде 32-битного int).

Если вы этого не хотите, вы можете написать "TEST" вручную, написав символы ASCII для каждой буквы в виде байтов, или вы можете использовать:

System.Text.Encoding.UTF8.GetBytes("TEST")

И напишите результирующий массив (который не будет содержать длину int)

Ответ 5

То, что вы видите, на самом деле представляет собой 7-битное кодированное целое число, которое является своего рода целочисленным сжатием.
BinaryWriter добавляет текст так, чтобы читатели (т.е. BinaryReader) знали, как долго написана строка.

Подробнее о деталях реализации можно прочитать в http://dpatrickcaldwell.blogspot.se/2011/09/7-bit-encoding-with-binarywriter-in-net.html.

Ответ 6

Вы можете сохранить его в виде байтового массива с кодировкой UTF8 следующим образом:

...

BinaryWriter w = new BinaryWriter(fs);

w.Write(UTF8Encoding.Default.GetBytes("test"));

...

Ответ 7

Это, скорее всего, байт. Это потому, что для кодирования потока установлено значение Юникод.

Ответ 8

Помните, что строки Java внутренне кодируются в UTF-16.

Итак, "тест" фактически сделан из байтов 0xff, 0xfe (вместе с байтом байта), 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00.

Возможно, вы захотите работать с байтами вместо потоков символов.