BinaryWriter пишет забавные персонажи - PullRequest
0 голосов
/ 10 июля 2019

Ниже приведен код:

using (FileStream fs = File.Create("data.txt"))
using (BinaryWriter bw = new BinaryWriter(fs))
{
   int num = 2019;
   bw.Write(num);
}

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

В1-Это потому, что код моего редактора - UTF-8, который несовместим с форматом BinaryWriter? какую схему кодирования использовать, чтобы увидеть действие 2019 в текстовом файле?

В2. Каковы практические применения BinaryWriter над другими потоковыми адаптерами, такими как StreamWriter? для меня BinaryWriter делает некоторые странные вещи, например, вы используете BinaryWriter, чтобы сначала написать int, а затем написать строку ..., затем, когда вы читаете файл с помощью BinaryReader, вы должны выполнить ReadInt32 () и затем ReadString ( ), вы не можете испортить последовательность, если вы выполните ReadString (), вы получите забавный персонаж. но кто будет «помнить» или знать последовательности для чтения?

Ответы [ 3 ]

2 голосов
/ 10 июля 2019

ОК, давайте начнем с того, что делает ваш код (см. Мои добавленные комментарии):

// create a FileStream to data.txt (a file with a .txt extension - not necessarily a text file) 
using (FileStream fs = File.Create("data.txt"))

// wrap the stream in the BinaryWriter class, which assists in writing binary files
using (BinaryWriter bw = new BinaryWriter(fs))
{
   // create a 32-bit integer
   int num = 2019;
   // write a 32-bit integer as 4 bytes
   bw.Write(num);
}

Первое, что вы заметите, это то, что вы пишете не текстовый файл, а двоичный файл. Расширения файлов являются соглашением и, возможно, говорят нам, что мы должны ожидать найти в файле, но это не истина Евангелия. Я мог бы взять копию Chrome.exe и переименовать ее в Chrome.txt, но это не делает ее текстовым файлом.

Какую схему кодирования я должен использовать, чтобы увидеть действие 2019 в текстовом файле?

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

Каковы практические применения BinaryWriter над другими потоковыми адаптерами, такими как StreamWriter?

Позволяет быстро создавать двоичный формат из значений в .NET. Например, вместо того, чтобы вручную преобразовывать значение int в 4 байта, вы можете вызвать bw.Write(num);, а также вы можете прочитать эти данные, используя, например, BinaryReader и br.ReadInt32().

Вы не можете испортить последовательность, если вы выполните ReadString (), вы получите забавный персонаж. но кто будет «помнить» или знать последовательности для чтения?

Когда мы говорим о «форматах файлов», мы обычно подразумеваем соглашения, которые мы соблюдаем при чтении файла. Причина, по которой мы можем запустить приложение, прочитать ZIP-файл, прослушать MP3-файл или просмотреть растровое изображение, заключается в том, что используемое нами программное обеспечение написано для понимания этих двоичных форматов.

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

Теперь, если бы вы создавали свой собственный формат, вы, вероятно, писали бы писателя и читателя одновременно или, по крайней мере, смотрели бы на код писателя, когда речь идет о написании читателя (если у вас нет спецификации для следуйте, в этом случае вы можете использовать это).

Но то, что я не получаю, это то, что вставленное мной int отображается как забавный символ, вставленная мной строка на самом деле читаема, так почему строка читаема, а не int?

Когда вы звоните Write(string), вы на самом деле пишете две вещи: информацию о длине строки и затем пишете саму строку. Для этого BinaryWriter необходимо преобразовать строку в байты, что она делает для вас за кулисами. Вы можете прочитать об этом здесь и в документации .

Так почему вы можете прочитать строку в вашем файле? Ну, это потому, что текстовая кодировка, используемая здесь, является той же кодировкой, которую вы могли бы использовать для написания текстового файла Ваш текстовый редактор сделает все возможное, чтобы отобразить содержимое всего файла. Это можно увидеть, если перетащить любой текстовый файл (например, Chrome.exe) в текстовый редактор.

Итак, как вы просматриваете содержимое вашего файла? Ну, вы можете использовать hex hex . Шестнадцатеричный редактор позволяет просматривать и редактировать двоичные файлы. Шестнадцатеричный редактор обычно отображает ваш файл как шестнадцатеричный с одной стороны, а попытка рендерить его как текст с другой.

Итак, представьте, что ваш код такой:

using (FileStream fs = File.Create("data.txt"))
using (BinaryWriter bw = new BinaryWriter(fs))
{
   int num = 2019;
   bw.Write(num);
   bw.Write("hello");
}

Если мы откроем его в шестнадцатеричном редакторе, мы увидим следующее. Обратите внимание, что пробелы между шестнадцатеричными значениями просто для облегчения чтения и не представляют ничего в файле:

E3 07 00 00 05 68 65 6C 6C 6F

Здесь есть три части:

E3 07 00 00    - the hexadecimal expression of little endian 2019
05             - indicating that the string is 5 _bytes_ long
68 65 6C 6C 6F - the hexadecimal representations of each character of the string "hello"

Вы можете прочитать о порядке байтов здесь . Думайте об этом как о том, пишет ли компьютер числа «слева направо» или «справа налево».

Так что, взглянув на значение int, хранящееся выше, мы можем записать его в двоичном формате (1 справа) в виде:

<  00   >  <  00   >  <  07   >  <  E3   >
0000 0000  0000 0000  0000 0111  1110 0011

Затем мы можем рассчитать это обратно до 2019 года, ваше первоначальное значение.

Обратите внимание, что информация о длине строки может быть больше одного (согласно этот ответ ).

1 голос
/ 10 июля 2019

Файлы представляют собой строки чисел - например, 13, 59, 93. Чтобы понять содержимое файла, вам нужен формат - по сути, описание того, что означает его содержимое.Чтобы просмотреть байты файла, вы можете использовать шестнадцатеричный редактор (вместо текстового редактора).

Одним из таких форматов является текстовый файл.Имейте в виду, что один формат текстового файла - как вы уже заметили, ваш текстовый редактор позволяет вам выбрать кодировку, которую он будет использовать при интерпретации текстового файла.Если вы выберете неправильную кодировку, текст будет другим (хотя вы можете не заметить, что большинство кодировок на английском языке, так как многие символы идентичны в большинстве современных кодировок).Кодировка - это то, что переводит число 65 (фактически сохраненное в файле) в символ 'A'.Помимо кодирования есть много других сложностей, о которых я расскажу позже.

Вы используете BinaryWriter.Как следует из названия, он предназначен для записи двоичных файлов, а не текстовых файлов.Если вы хотите писать простые текстовые файлы, используйте вместо этого StreamWriter.Двоичный файл, как правило, более компактен, чем текстовый файл, предназначенный для использования конкретными приложениями, а не для непосредственного чтения или изменения пользователями.Вы все еще можете писать текст в двоичном файле - это именно то, что делает bw.Write("Hello");и поскольку он использует ту же кодировку (по умолчанию), что и ваш текстовый редактор, вы фактически видите слово «Hello» в своем редакторе.Имейте в виду, есть также «забавные символы» перед «Привет» - но для такой короткой строки они не видимы (некоторые могут отображаться в виде пробела, другие в качестве элемента управлениятакие символы, как «конец строки» или «табуляция», вы даже можете написать звуковой сигнал , который будет выполнен, если вы распечатаете файл).Они представляют длину следующей строки, которая позволяет вам быстро прочитать строку, и только строку (или пропустить ее во время чтения файла).

Теперь для чтения и записи файлов требуется определенноесимметрии.Как вы заметили, если вы напишите файл как «сначала число, затем строка», вам также нужно прочитать как «сначала число, а затем строка».Не имеет значения, является ли файл текстовым или двоичным файлом - например, скажем, вы хотите записать координаты GPS в файл.Если вы сначала напишите широту, а затем долготу, другая программа (или пользователь), считывающая файл как долготу, сначала получит неправильный результат.Простой формат файла, подобный этому, зависит от порядка и абсолютно не допускает ошибок любого рода - пропустите одну строку при чтении или записи, и все это станет совершенно нечитаемым.

Но, конечно, это не единственный способВы можете создать формат файла (хотя это, безусловно, очень распространено).Существуют форматы, специально разработанные для того, чтобы быть менее строгими.Например, вместо набора строк или значений, разделенных запятыми, вы можете сохранить свои данные в файле JSON:

{
  "longitude": 12.365,
  "lattitude": 32.131
}

Основное преимущество заключается в том, что формат является более информативным и удобочитаемым для человека (и для записи);Вы можете сразу увидеть, что широта 32.131.Приложение все еще должно понимать, что такое «широта», но вы можете видеть, что здесь есть определенный прогресс.Он также более терпим к некоторым видам изменений - например, приложению для чтения не нужно заботиться о том, что некоторые поля отсутствуют (и отображают не полную информацию, а не полный беспорядок), или если добавляются новые поля.Это не заботится о порядке полей.

Это происходит за плату.Файл на намного больше (простой двоичный файл может иметь размер 8 байт или меньше по сравнению с ~ 40 байтами или около того для образца JSON; это становится еще более выраженным, если задействованы массивы и т. Д.).Анализировать программу намного сложнее, что может замедлить загрузку файла.Не строгое отношение к формату также имеет свои преимущества и недостатки - может быть очень трудно гарантировать, что программа правильно обрабатывает все потенциальные входные данные, особенно если есть несколько разных читателей и писателей.

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

В конце концов, вам нужно выбрать формат, который вы хотите использовать для сохранения материала. Каждый имеет свой набор преимуществ и недостатков. Некоторые из них очень просты, например, просто используйте BinaryWriter для написания известной последовательности. Некоторые поддерживают совместимость версий, поэтому новое приложение может читать или записывать файлы старого приложения или наоборот. Некоторые из них специально оптимизированы для определенных целей, таких как включение быстрого поиска по содержимому файла или эффективное хранение изображений. Некоторые из них предназначены в основном для простоты использования (например, JSON и Protobuf или .NET BinarySerializer).

Но, в конце концов, файл представляет собой просто строку чисел. Вам нужны правила, чтобы интерпретировать эти цифры, чтобы быть полезными. Выберите правила, соответствующие вашим потребностям.

1 голос
/ 10 июля 2019

Все зависит от формата файла.

Когда вы используете StreamWriter, ваш вывод будет в читаемом тексте, что означает, что вы можете видеть то, что внутри, в редакторе.Например, вы можете написать bool "true" или "false". При использовании бинарного устройства записи значение сохраняется в его двоичном представлении, которое будет 0 или 1 для логического значения.Обратите внимание, что вы можете в текстовом файле написать "0" для true, если хотите.

Когда дело доходит до запоминания того, что находится внутри, либо вы используете формат файла с самоописанием, такой как csv с заголовками илиВы должны использовать стандартный формат (например, MP3, для которого вы можете найти описание в Интернете), или вы должны писать и читатель, и писатель одновременно, чтобы убедиться, что они совпадают (даже с текстовым форматом).

Например, взглянув на "0,0", вы не сможете определить, является ли его два логических значения, разделенных запятой, или числом 0 во французском формате с точностью до одной цифры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...