我创建了一个Python脚本来使用霍夫曼算法压缩文本。说我有以下字符串:
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'
如何从此结果返回到原始字符串?还是我完全错了?谢谢!
答案 0 :(得分:3)
首先,您需要将输入字符串转换为字节:
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'