0

我正在python (2.7) 中做基本Lempel-Ziv压缩的变体。情况是,这个算法通常会输出一个由字符和整数组成的列表,最后一个指定字典中每个新字符串的顺序。

现在,假设我们压缩了一个足够大的文件,因此会出现高达 400000 或更多的整数,所以我正在做的是将这些整数中的每一个传递给二进制文件,将二进制文件分解为最多 8 位字节(例如 400000 的二进制形式是一个 1 和 0 的大约 18 位或 19 位的字符串,因此它可以分解为 2 个 8 位字节和一个 2 位或 3 位字节),这样每个 6 -character 整数将减少到 3 个字符。细绳。请注意,即使是 3 位整数也会减少到 2 字符。字符串,这样LZW算法得到的列表更紧凑。

发生的情况是,我能够正确地使用代码压缩文件(从 2.2 Mb 到 1.5 Mb),或者我认为是这样,但是当我解压缩它时,我没有获得完全相同的初始文本。

这是我的压缩代码:

def encode(order):
    danger = [0, 9, 10, 13, 32, 222, 255, 256]
    str2 = ""
    str3 = ""
    binary = bin(order)[2:]
    for bit in binary:
        str2 += bit
        if len(str2) == 8:
            helper = int(str2,2)
            if helper in danger:
                str3 = chr(222)+str(order) #222 is choosable, may be another ASCII one
                str2 = ""
                break
            else:
                str3 += chr(int(str2,2)) 
                str2 = ""
    if str2 != "":
        helper = int(str2,2)
        if helper in danger:
            str3 = chr(222)+str(order)
        else:
            str3 += chr(int(str2,2))
    return str3

file_in = open("donquijote.txt")
file_out = open("compressed5.txt","w")

codes = dict([(chr(x), x) for x in range(256)])
danger = [0, 9, 10, 13, 32, 222, 255, 256]      
code_count = 257
current_string = ""
string = file_in.read()
for c in string:
    current_string = current_string + c
    if not current_string in codes:
        codes[current_string] = code_count
        if (codes[current_string[:-1]] < 257) & (codes[current_string[:-1]] not in danger):
            file_out.write(chr(codes[current_string[:-1]])+" ")
        else:
            str4 = encode(codes[current_string[:-1]])
            file_out.write(str4+" ")
        code_count += 1
        current_string = c
file_out.write(encode(codes[current_string]))

file_in.close()
file_out.close()

好的,所以所有这一切的棘手部分是,当我将压缩代码写入文件时,为了保持它的“列表”格式,我用空格分隔列表的每个组件,因此我m 节省逗号(传统列表类似于 ['A', 'B, 'C', ...])。因此,我定义了一个列表 -危险- 其中包含可能使这种“幻像列表”格式消失的有问题的字符,例如空格、空值、制表符等。当其中一个出现时,我保持它是整数通过在前面放置相同的字符来引用字典(我选择它是222- 对应的 ASCII,虽然它可能是另一个),它也包含在“危险”列表中。这样,在解压过程中,当这个字符出现时,代码自动知道他后面的序列必须直接保存为字典的参考,而不是再解码为二进制和混淆。

这是我的解压代码:

output = open("compressed5.txt")
descomp = open("decompressed5.txt","w")

text = output.read()
compressed_data = text.split()
strings = dict([(x, chr(x)) for x in range(256)])

next_code = 257
previous_string = ""
binary = ""
a = 1
for element in compressed_data:
    for char in element:
        if ord(char) == 222:
            c = int(element[1:])
            break
        else:
            binary += bin(ord(char))[2:]
            if a == len(element):
                c = int(binary,2)
                a = 1
            else:
                a += 1
    binary = ""
    if not (strings.has_key(c)):
        strings[c] = previous_string + (previous_string[0])
    descomp.write(strings[c])
    if not(len(previous_string) == 0):
        strings[next_code] = previous_string + (strings[c][0])
        next_code +=1
    previous_string = strings[c]

output.close()
descomp.close()

我看不出我在这里缺少什么(实际上我是 python 的新手),或者我是否应该考虑在危险列表中添加另一个有问题的字符以避免与“列表”发生某种冲突"格式化。或者我可以使用另一种方式将这个列表以紧凑的形式写入输出文件,而不会丢失它的格式。

非常感谢任何形式的帮助!

4

0 回答 0