python

时间:2015-11-19 04:57:40

标签: python algorithm compression lzw

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

现在,假设我们压缩一个足够大的文件,因此会出现高达400000或更多的整数,所以我正在做的是将每个整数传递给二进制,将二进制分解为up-to -8位字节(例如,400000的二进制形式是一个大约18或19位的1和0的字符串,因此它可以分解为2个8位字节和2或3位的字节),这样每个6个字符的整数将减少为3个字符。串。请注意,即使是3位整数也会减少为2-char。字符串,这样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()

好的,所有这一切中棘手的部分是因为我将压缩代码写入文件,并且为了维护它而列出&#34;列表&#34;格式我用空格分隔列表的每个组成部分,因此我节省了逗号(传统列表就像[&#39; A&#39;,&#39; B,&#39 ; C&#39;,...])。由于这个原因,我已经定义了一个列表 - 危险 - 其中包含有问题的字符,可以使这个&#34;幻像列表&#34;格式消失,例如空格,空值,制表符等。当其中一个出现时,我通过将相同的字符放在前面来维护它对字典的整数引用(我已选择它作为 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中的新手),或者我是否应该考虑在危险列表中添加另一个有问题的角色以避免某种与&#34; list&#34;的冲突?格式。或者我可以使用其他方式将此列表在紧凑的表单上写入输出文件而不会丢失它的格式。

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

0 个答案:

没有答案