【问题标题】:How to write Huffman coding to a file using Python?如何使用 Python 将 Huffman 编码写入文件?
【发布时间】:2018-12-27 18:26:02
【问题描述】:

我创建了一个 Python 脚本来使用 Huffman 算法压缩文本。假设我有以下字符串:

string = 'The quick brown fox jumps over the lazy dog'

运行我的算法会返回以下“位”:

result = '01111100111010101111010011111010000000011000111000010111110111110010100110010011010100101111100011110001000110101100111101000010101101110110111000111010101110010111111110011000101101000110111000'

通过将结果的位数与输入字符串进行比较,该算法似乎有效:

>>> print len(result), len(string) * 8
194 344

但现在问题来了:我如何将其写入文件,同时仍然能够对其进行解码。您只能按字节写入文件,而不能按位写入文件。通过将“代码”写入字节,根本没有压缩!

我是计算机科学的新手,在线资源对我来说并不合适。非常感谢所有帮助!

编辑:请注意,我的代码是这样的(如果是另一个输入字符串 'xxxxxxxyzz'):

{'y': '00', 'x': '1', 'z': '10'}

我创建结果字符串的方法是按照输入字符串的顺序连接这些代码:

result = '1111111001010'

如何从这个结果中恢复到原始字符串?还是我完全错了?谢谢!

【问题讨论】:

  • 当然可以转换这样的字符串,但这真的是您想要做的吗?那样的话,暂时的结果仍然会很大。
  • @harold 将文件存储为 25 个字节而不是 43 个字节是一个约 40% 的改进,这似乎是值得的。您指的是什么临时结果?
  • @MoxieBall "bits" 字符串,每组 8 个字符转换为一个字节。
  • @harold 明白了。所以你只是建议 OP 以一种不会立即创建该字符串的方式执行此操作?

标签: python encoding compression huffman-code


【解决方案1】:

首先您需要将输入字符串转换为字节:

def _to_Bytes(data):
  b = bytearray()
  for i in range(0, len(data), 8):
    b.append(int(data[i:i+8], 2))
  return bytes(b)

然后,打开一个文件以二进制模式写入:

result = '01111100111010101111010011111010000000011000111000010111110111110010100110010011010100101111100011110001000110101100111101000010101101110110111000111010101110010111111110011000101101000110111000'
with open('test.bin', 'wb') as f:
  f.write(_to_Bytes(result))

现在,将原始字符串写入文件,可以进行字节比较:

import os
with open('test_compare.txt', 'a') as f:
  f.write('The quick brown fox jumps over the lazy dog')

_o = os.path.getsize('test_compare.txt')
_c = os.path.getsize('test.bin')
print(f'Original file: {_o} bytes')
print(f'Compressed file: {_c} bytes')
print('Compressed file to about {}% of original'.format(round((((_o-_c)/_o)*100), 0)))

输出:

Original file: 43 bytes
Compressed file: 25 bytes
Compressed file to about 42.0% of original

要回到原来的状态,您可以编写一个函数来确定可能的字符顺序:

d = {'y': '00', 'x': '1', 'z': '10'}
result = '1111111001010'
from typing import Generator
def reverse_encoding(content:str, _lookup) -> Generator[str, None, None]:
  while content:
    _options = [i for i in _lookup if content.startswith(i) and (any(content[len(i):].startswith(b) for b in _lookup) or not content[len(i):])]
    if not _options:
      raise Exception("Decoding error")
    yield _lookup[_options[0]]
    content = content[len(_options[0]):]

print(''.join(reverse_encoding(result, {b:a for a, b in d.items()})))

输出:

'xxxxxxxyzz'

【讨论】:

  • 感谢您的回答!我编辑了我的帖子以澄清我关于文件解码的问题。
  • 谢谢,这就是我要找的!
  • @PimKlaassen 很高兴为您提供帮助
猜你喜欢
  • 2022-06-15
  • 2020-01-22
  • 1970-01-01
  • 1970-01-01
  • 2013-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
相关资源
最近更新 更多