Общий вопрос о двоичных файлах - PullRequest
8 голосов
/ 26 марта 2011

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

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

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

Ответы [ 6 ]

4 голосов
/ 26 марта 2011

Когда я пишу в файл в двоичном режиме (в Python), я просто пишу обычный текст.

Вам придется изменить свой подход при обновлении до Python 3.x:

>>> f = open(filename, 'wb')
>>> f.write("Hello, world!\n")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be bytes or buffer, not str
>>> f.write(b"Hello, world!\n")
14

Но ваш вопрос на самом деле не о бинарных файлах. Это примерно str.

В Python 2.x str - это последовательность байт , которая имеет перегруженное значение:

  • Строка, отличная от Unicode, или
  • Необработанные двоичные данные (например, пиксели на изображении).

Если вы напечатаете последний, как он был первым, вы получите бред.

Python 3.x избавился от этого двойного значения, введя отдельный тип bytes для двоичных данных, однозначно оставив str в виде текстовой строки (и сделав его Unicode).

4 голосов
/ 26 марта 2011

Вот буквальный ответ на ваш вопрос:

import struct
with open('gibberish.bin', 'wb') as f:
    f.write(struct.pack('<4d', 3.14159, 42.0, 123.456, 987.654))

Это упаковывает эти 4 числа с плавающей запятой в двоичный формат (little-endian IEEE 756 64-битная с плавающей запятой).

Вот (некоторые из), что вам нужно знать:

Чтение и запись файла в двоичном режиме не приводит к преобразованию данных, которые вы читаете или записываете. В текстовом режиме, а также при любом декодировании / кодировании в / из Unicode данные, которые вы читаете или записываете, преобразуются в соответствии с соглашениями платформы для «текстовых файлов».

Unix / Linux / Mac OS X: без изменений

старый Mac: разделитель строк \r, изменен на / из стандарта Python \n

Windows: разделитель строк - \r\n, изменен на / с \n. Также (малоизвестный факт), Ctrl-Z или \x1a интерпретируется как конец файла, соглашение, унаследованное от CP/M, которое записывает размеры файлов как число используемых 128-байтовых секторов.

3 голосов
/ 26 марта 2011

Так называемые «текстовые» файлы - это просто файлы, которые следуют определенным соглашениям: байты, как правило, являются подмножеством всех возможных байтов, обычно значениями ASCII или Unicode, и организованы в «строки» с «разделителями строк». Стандартные ограничители строки различаются в зависимости от платформы - Unix использует \n, Mac \r и Windows \r\n, поэтому часть соглашения заключается в их переводе на лету. Это отлично работает с текстовыми файлами, но затирает другие типы файлов, потому что 0x0a (\n) байт в звуковом файле или что-то не очень хорошо для преобразования в 0x0d 0x0a (* 1008) *). Конечно, если вы используете только Unix, этого не произойдет.

В Python 3 все строки являются Unicode, и открытие файла в виде текста означает, что вы должны читать и записывать строки Unicode и, возможно, указывать кодировку (по умолчанию UTF-8). Открытие файла в двоичном виде означает, что вы должны использовать bytes объекты, которые являются простыми списками 8-битных байтов и не кодируются.

Это проясняет ситуацию?

2 голосов
/ 26 марта 2011

Двоичные файлы обычно создаются при попытке кодирования объектов. Например, у вас может быть объект Person со свойствами, такими как Имя, Возраст, Высота. Если вы хотите записать этот файл в виде текста, чтобы его можно было прочитать позже, вы можете вывести что-то вроде этого:

Name:Ralph
Age:25
Height:5'6"

Но вы можете представить его более компактно в двоичном виде. В двоичном коде вы можете просто выводить имя, возраст и рост один за другим, и вам придется считывать их обратно в том же порядке, поскольку у вас больше нет этих разделителей. В этом случае ваша строка должна была бы быть закодирована чем-то вроде Ralph\0. \0 является нулевым символом, поэтому он знает, где заканчивается строка.

25 можно представить как 2 символа в тексте / ASCII, но если вы попытаетесь поставить два числа рядом, например, 25 и 26, вы получите 2526, и вы не будете знать, где заканчивается один и начинается следующее Эти числа на самом деле являются целыми числами и представлены 4 байтами. Когда вы записываете файл в двоичном виде, вы записываете все 4 байта, даже если самые левые биты равны 0. Таким образом, он всегда точно знает, сколько его нужно прочитать. И так далее ...

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

Чтобы сгенерировать эти файлы, вы должны будете закодировать или «упаковать» ваши данные, как предлагает Джон Мачин.

0 голосов
/ 26 марта 2011

Я рекомендую использовать модуль Python codecs для написания текстовых файлов (он позволяет вам установить соответствующую кодировку / кодировку).Для записи двоичного файла используйте стандартный метод file ().В Windows вам может понадобиться использовать «wb» или «rb» для бинарных режимов (не имеет значения в Unix).

0 голосов
/ 26 марта 2011

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

...