Передача последовательности битов в файл python

В рамках более крупного проекта я хочу сохранить последовательность битов в файле, чтобы файл был как можно меньше. Я не говорю о сжатии, я хочу сохранить последовательность как есть, но используя наименьшее количество символов. Первоначальная идея состояла в том, чтобы превратить мини-последовательности из 8 бит в символы, используя кодировку ASCII, и сохранить эти символы, но из-за какой-то неизвестной проблемы со странными символами символы, извлеченные при чтении файла, не совпадают с теми, которые были изначально записаны. Я пытался открыть файл с кодировкой utf-8, latin-1, но ничего не работает. Мне интересно, есть ли другой способ, может быть, превратить последовательность в шестнадцатеричное число?


person Julen Cestero    schedule 15.01.2017    source источник
comment
Имейте в виду, что ASCII имеет только 7 бит. Старший бит (так сказать, бит 8) всегда устанавливается равным нулю.   -  person Willem Van Onsem    schedule 16.01.2017
comment
Почему вы вообще храните их в виде текста? Откройте файл в двоичном режиме. Если биты не кратны восьми, вам нужен дополнительный байт для описания количества допустимых битов в последнем байте, но в противном случае вы просто сохраните необработанные байты, а не в какой-либо конкретной кодировке.   -  person ShadowRanger    schedule 16.01.2017
comment
Да, вы должны использовать их в двоичном режиме. Вот страница, на которой рассказывается о битовых массивах в Python: wiki.python.org/moin/BitArrays .   -  person Miloslav Číž    schedule 16.01.2017
comment
Вы можете использовать типы bytearray или bytes Python, как описано здесь: stackoverflow.com/questions/18367007/   -  person SergeyLebedev    schedule 16.01.2017
comment
Вот демонстрационный изменяемый бит-векторный класс , который, кажется, был написан Гвидо. Также есть вопрос Записать логическую строку в двоичный файл?   -  person martineau    schedule 16.01.2017


Ответы (1)


технически вы не можете написать меньше байта, потому что ОС организует память в байтах (записать отдельные биты в файл на python), так что это двоичный файл io, см. https://docs.python.org/2/library/io.html есть такие модули, как struct

откройте файл с помощью переключателя 'b', указывает на операцию двоичного чтения/записи, затем используйте, например, функцию to_bytes() (Запись битов в двоичный файл) или struct.pack() (Как записать отдельные биты в текстовый файл в python?)

  with open('somefile.bin', 'wb') as f:

 import struct
 >>> struct.pack("h", 824)
'8\x03'

>>> bits = "10111111111111111011110"
>>> int(bits[::-1], 2).to_bytes(4, 'little')
b'\xfd\xff=\x00'

если вы хотите обойти 8-битную (байтовую) структуру памяти, вы можете использовать манипулирование битами и такие методы, как битовые маски и BitArrays, см. https://wiki.python.org/moin/BitManipulation и https://wiki.python.org/moin/BitArrays

однако проблема, как вы сказали, заключается в том, чтобы считывать данные, если вы используете BitArrays разной длины, то есть для хранения десятичного числа 7 вам нужно 3 бита 0x111 для хранения десятичного числа 2 вам нужно 2 бита 0x10. теперь проблема в том, чтобы прочитать это обратно. как ваша программа может узнать, должна ли она считывать значение обратно как 3-битное значение или как 2-битное значение? в неорганизованной памяти десятичная последовательность 72 выглядит как 11110, которая преобразуется в 111|10, поэтому как ваша программа может узнать, где находится |?

в обычной памяти с упорядоченным байтом десятичное число 72 равно 0000011100000010 -> 00000111|00000010 это имеет то преимущество, что ясно, где находится |

вот почему память на самом низком уровне организована в виде фиксированных кластеров по 8 бит = 1 байт. если вы хотите получить доступ к отдельным битам внутри байтов/8-битных кластеров, вы можете использовать битовые маски в сочетании с логическими операторами (http://www.learncpp.com/cpp-tutorial/3-8a-bit-flags-and-bit-masks/ ). в python самый простой способ манипуляции с одним битом - это модуль ctypes

если вы знаете, что все ваши значения 6-битные, возможно, это стоит усилий, однако это тоже сложно...

(Как установить, очистить, и переключить один бит?)

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

person ralf htp    schedule 15.01.2017
comment
Спасибо за вашу помощь, но мы попробовали эти методы, и то, что мы закончили писать в нашем файле, было каждый бит как char. Возможно, вопрос задан неправильно, мы хотим найти оптимальный контейнер для этих битов, чтобы их можно было записать в файл с наименьшим возможным размером. Это возможно? Мы пытались взять каждые 7 бит и преобразовать в char, но когда мы попытались восстановить исходную последовательность, это привело к ошибкам... - person Julen Cestero; 16.01.2017