哈夫曼编码:如何用Python编写二进制数据
我已经尝试过使用struct模块的方法,如代码中注释的行所示,但没有成功。基本上,我有两个选择:我可以逐个代码编写二进制数据代码(我的代码是长度从3位到13位不等的位序列),或者将整个n个字符字符串(在这种情况下,n=25000+)转换为二进制数据。但我不知道如何实现这两种方法。代码:哈夫曼编码:如何用Python编写二进制数据,python,binary,binary-data,huffman-code,Python,Binary,Binary Data,Huffman Code,我已经尝试过使用struct模块的方法,如代码中注释的行所示,但没有成功。基本上,我有两个选择:我可以逐个代码编写二进制数据代码(我的代码是长度从3位到13位不等的位序列),或者将整个n个字符字符串(在这种情况下,n=25000+)转换为二进制数据。但我不知道如何实现这两种方法。代码: import heapq import binascii import struct def createFrequencyTupleList(inputFile): frequencyDic = {}
import heapq
import binascii
import struct
def createFrequencyTupleList(inputFile):
frequencyDic = {}
intputFile = open(inputFile, 'r')
for line in intputFile:
for char in line:
if char in frequencyDic.keys():
frequencyDic[char] += 1
else:
frequencyDic[char] = 1
intputFile.close()
tupleList = []
for myKey in frequencyDic:
tupleList.append((frequencyDic[myKey],myKey))
return tupleList
def createHuffmanTree(frequencyList):
heapq.heapify(frequencyList)
n = len(frequencyList)
for i in range(1,n):
left = heapq.heappop(frequencyList)
right = heapq.heappop(frequencyList)
newNode = (left[0] + right[0], left, right)
heapq.heappush(frequencyList, newNode)
return frequencyList[0]
def printHuffmanTree(myTree, someCode,prefix=''):
if len(myTree) == 2:
someCode.append((myTree[1] + "@" + prefix))
else:
printHuffmanTree(myTree[1], someCode,prefix + '0')
printHuffmanTree(myTree[2], someCode,prefix + '1')
def parseCode(char, myCode):
for k in myCode:
if char == k[0]:
return k[2:]
if __name__ == '__main__':
myList = createFrequencyTupleList('input')
myHTree = createHuffmanTree(myList)
myCode = []
printHuffmanTree(myHTree, myCode)
inputFile = open('input', 'r')
outputFile = open('encoded_file2', "w+b")
asciiString = ''
n=0
for line in inputFile:
for char in line:
#outputFile.write(parseCode(char, myCode))
asciiString += parseCode(char, myCode)
n += len(parseCode(char, myCode))
#values = asciiString
#print n
#s = struct.Struct('25216s')
#packed_data = s.pack(values)
#print packed_data
inputFile.close()
#outputFile.write(packed_data)
outputFile.close()
你在找这个:
packed_data = ''.join(chr(int(asciiString[i:i+8], 2))
for i in range(0, len(asciiString), 8))
它将从ascistring
一次获取8位,将其解释为一个整数,并输出相应的字节
这里的问题是,这需要ascistring
的长度为8位的倍数才能正常工作。否则,将在最后几个实位之前插入零位
因此,您需要将最后一个字节中的位数存储在某个位置,这样您就知道在取回这些位时忽略它们,而不是将它们解释为零。你可以试试:
packed_data = chr(len(asciiString) % 8) + packed_data
然后当你读回来的时候:
packed_input = coded_file.read()
last_byte_length, packed_input, last_byte = (packed_input[0],
packed_input[1:-1],
packed_input[-1])
if not last_byte_length: last_byte_length = 8
ascii_input = ''.join(chain((bin(ord(byte))[2:].zfill(8) for byte in packed_input),
tuple(bin(ord(last_byte))[2:].zfill(last_byte_length),)))
# OR
# ascii_input = ''.join(chain(('{0:0=8b}'.format(byte) for byte in packed_input),
# tuple(('{0:0=' + str(last_byte_length) + '8b}').format(last_byte),)))
编辑:您需要从bin()
返回的字符串中删除“0b”,或者在2.6或更高版本上,最好使用我添加的新的替代版本,该版本使用字符串格式,而不是bin()
、切片和zfill()
编辑:谢谢eryksun,很好地使用链来避免复制ASCII字符串。另外,需要在
bin()
版本中调用ord(byte)
。我认为这是一个改进。在Python3中,不使用b“”类型来存储文本,而是存储二进制数据,因此它非常有意义。为什么要对二进制数据调用ord
?你不会的,你称之为角色。二进制数据的单个字节最容易表示为整数,这就是Python 3的功能。是否所有支持{0}.format()的Python版本都支持嵌套版本?我知道'{}.format()
不能在所有接受'{0}.format()
的版本中工作。谢谢,这非常准确,但对我来说也很难理解。我不明白为什么写二进制数据这么复杂。。。