преобразовать строку кода Хаффмана в двоичный файл

1

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

Этот вопрос не содержит ничего из алгоритма хаффмана.

Это так:

Я могу получить закодированную строку хаффмана, скажем, 01010101010. Обратите внимание, что это строка.

Но теперь я хочу сохранить представление строки в реальном двоичном файле.

В закодированной строкой huffman каждые 0 и 1 являются байтами.

Я хочу, чтобы каждый 0 и 1 был немного.

Как я могу это сделать в python?

Изменить 1:

Пожалуйста, простите, я не описал свою проблему достаточно ясно.

Позвольте мне объяснить мой нынешний подход к написанию нулей и единиц в двоичный файл.

Скажем, мы можем ввести строку кода s = '010101010'.

  1. Я использую int чтобы преобразовать его в integer
  2. Затем используйте unichr чтобы преобразовать его в строку, чтобы я мог записать его в файл
  3. записать строку в файл в двоичном режиме

Также следует отметить, что мне нужно прочитать файл, чтобы декодировать код huffman.

Поэтому мой подход,

  1. читать байты из файла
  2. восстановить их до int
  3. преобразуйте int в свою двоичную строку представления.
  4. декодировать строку

И на шаге 2 проблема возникает, и я стал невежественным.

Поскольку некоторые строки хаффмана могут быть короткими (например, 10), а некоторые могут быть длинными (010101010101001). Это приводит к их разной длине байтов в их значении int (некоторая короткая строка может принимать только один байт, а длинные - две или даже больше)

Следующий код иллюстрирует мою проблему:

ss=['010101','10010101010'] 
# first one is short and takes only one byte in its int value
# second one is long and takes two bytes   

print 'write it to file'
with open('binary.bin','wb') as f:
    for s in ss:
        n=int(s,2)
        print n
        s=unichr(n)
        f.write(s)

print 'read it to file'
with open('binary.bin','rb') as f:
    for s in f.read(): 
        print ord(s)

Я читаю один байт во второй раз с частью, но на самом деле это неверно. Потому что строка 10010101010 занимает два байта.

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

  • 0
    Существует ранняя версия кодера Хаффмана, которую я написал вместе по адресу pastebin.com/QEK3WdbE, которая показывает, как я это делаю.
Показать ещё 3 комментария
Теги:
binary
huffman-code

3 ответа

2
Лучший ответ

Один из возможных подходов (с использованием библиотеки bitstring), который имеет определенный смысл, но по-прежнему содержит некорректность:

Используйте библиотеку битовых строк (благодаря механической улитке и марку B)

Для записи в файл.

шаги:

  1. кодировать простой текст в двоичную строку представления
  2. объединить все эти строки, чтобы сформировать один длинный
  3. использовать bitstring.BitArray для преобразования в шестнадцатеричный формат
  4. записать шестнадцатеричную строку в файл

Для чтения:

  1. читать шестнадцатеричную строку из файла
  2. конвертировать его обратно в битовую строку с помощью BitArray
  3. начать декодирование

Код:

ss=['01010100','10010101010','010101110101010101'] #encoded message


from bitstring import BitArray,BitStream
print 'write it to file'
with open('binary.bin','wb') as f:
    s=''.join(ss);
    b=BitArray(bin=s)                 
    f.write(b.tobytes())# thanks to Scott, tobytes() method is very useful

print 'read it to file'
b=BitArray(filename='binary.bin')
print b.bin
  • 1
    Проблема в том, что вы пишете в файл шестнадцатеричную строку , а не двоичные данные. То есть вы записываете 12-байтовую строку 0x0a92a95d55 в файл вместо 5 байтов \n\x92\xa9]U Вы могли бы просто написать 01010100... в файл! Я бы посоветовал использовать метод b.tobytes() для преобразования в байты (которые b.tobytes() нулевыми битами до границы байта). Эти дополнительные биты в конце могут быть проигнорированы декодером, так как они не будут декодироваться ни к одному символу. Также важно дополнять в конце, а не в начале.
  • 1
    Поэтому для записи просто используйте f.write(BitArray(bin=''.join(ss)).tobytes()) а для чтения вы можете использовать BitArray(filename='binary.bin') или создать его из чтения -только файл объекта BitArray(f) .
Показать ещё 4 комментария
2

В Python есть два разных "двоичных" представления, которые вы, возможно, захотите использовать.

Bignum

Один из них является "бигнем" или целым числом произвольной точности. Этот тип называется long в Python 2.x и int в Python 3.x. Как следует из названия, это представление семантически является целым числом произвольной длины, поэтому полезно, если вы планируете делать арифметику по полученному числу. Чтобы проанализировать строку двоичных цифр, используйте

# Python 2
long(digit_str, 2)

или

# Python 3
int(digit_str, 2)

библиотека bitstring

В качестве альтернативы, как предлагает Marc B в комментариях, используйте библиотеку bitstring. В частности, для преобразования используйте функцию bitstring.pack.

Для кодирования Хаффмана использование bitstring, вероятно, предпочтительнее хранения данных в byte -string, поскольку коды Хаффмана обычно не кратно 8 бит; bitstring позволяет вам манипулировать бит -string s произвольной длины. Недостаток: bitstring не входит в стандартную библиотеку.

1

У вас есть строка, которую нужно преобразовать в число. int принимает необязательную "базу" в качестве аргумента. Итак, для строки в вашем примере,

>>> int('01010101010', 2)
682

Когда у вас есть номер (а не строка), не имеет смысла хотеть "реальный" двоичный код, так как номер один и тот же, вы можете отображать его на любой базе. Это означает, что двоичный код 100 - это то же число, что и десятичное число 4, внутри вашей программы они не разные числа. Итак, как только вы превратите свою строку в число, вы можете играть с битами в ней.

  • 2
    '01' и '1' это разные коды. Вам необходимо кодировать количество битов, а также значение битов.
  • 0
    Хороший вопрос, я взял «Этот вопрос не имеет ничего общего с алгоритмом Хаффмана» за чистую монету, также не заметил повторяющийся вопрос со вчерашнего дня.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню