2009-08-22 49 views
7

Được rồi vì vậy tôi có một số luồng dữ liệu được nén bởi hàm zlib.compress() của python (2.6). Khi tôi cố gắng giải nén chúng, một số trong chúng sẽ không giải nén được (lỗi zlib -5, mà dường như là một "lỗi đệm", không biết phải làm gì). Lúc đầu, tôi nghĩ rằng tôi đã làm xong, nhưng tôi nhận ra rằng tất cả những cái tôi không thể giải nén bắt đầu với 0x78DA (những người đang làm việc là 0x789C), và tôi nhìn xung quanh và nó có vẻ là một loại nén zlib khác nhau - ma thuật số thay đổi tùy thuộc vào nén được sử dụng. Tôi có thể sử dụng những gì để giải nén các tập tin? Tôi có được nuôi không?giải nén zlib trong python

+0

Vui lòng chỉ định phiên bản của thư viện zlib mà trình thông dịch Python của bạn đã được biên dịch. –

+0

nó sẽ giúp ích rất nhiều nếu chúng ta có thể thấy mã bạn đã sử dụng để tạo luồng. Có thể phiên bản với 0x78DA được ghi vào đĩa bằng một lỗi, có thể mã hóa có liên quan? – Nelson

Trả lời

26

Theo RFC 1950, sự khác biệt giữa các 0x789C "OK" và "xấu" 0x78DA là trong FLEVEL bit lĩnh vực:

FLEVEL (Compression level) 
    These flags are available for use by specific compression 
    methods. The "deflate" method (CM = 8) sets these flags as 
    follows: 

     0 - compressor used fastest algorithm 
     1 - compressor used fast algorithm 
     2 - compressor used default algorithm 
     3 - compressor used maximum compression, slowest algorithm 

    The information in FLEVEL is not needed for decompression; it 
    is there to indicate if recompression might be worthwhile. 

"OK" sử dụng 2, "xấu" sử dụng 3. Vì vậy, sự khác biệt đó không phải là vấn đề.

Để tiếp tục, bạn có thể xem xét cung cấp thông tin sau cho mỗi lần nén và (cố gắng) giải nén: nền tảng nào, phiên bản Python, phiên bản thư viện zlib, mã thực tế được sử dụng để gọi mô-đun zlib. Đồng thời cung cấp đầy đủ thông tin truy xuất và thông báo lỗi từ các nỗ lực giải nén không thành công. Bạn đã thử giải nén các tập tin bị lỗi với bất kỳ phần mềm đọc zlib nào khác? Với kết quả gì? Vui lòng làm rõ những gì bạn phải làm việc với: "Tôi có được mời không?" có nghĩa là bạn không có quyền truy cập vào dữ liệu gốc? Làm thế nào nó nhận được từ một dòng vào một tập tin? Bạn đảm bảo rằng dữ liệu nào không bị xáo trộn khi truyền?

CẬP NHẬT Một số quan sát dựa trên giải thích một phần công bố trong tự câu trả lời của bạn:

Bạn đang sử dụng Windows. Windows phân biệt giữa chế độ nhị phân và chế độ văn bản khi đọc và ghi tệp. Khi đọc ở chế độ văn bản, Python 2.x thay đổi '\ r \ n' thành '\ n' và thay đổi '\ n' thành '\ r \ n' khi viết. Đây không phải là một ý tưởng hay khi xử lý dữ liệu phi văn bản. Tồi tệ hơn, khi đọc ở chế độ văn bản, '\ x1a' hay còn gọi là Ctrl-Z được coi là cuối tập tin.

Để nén một file:

# imports and other superstructure left as a exercise 
str_object1 = open('my_log_file', 'rb').read() 
str_object2 = zlib.compress(str_object1, 9) 
f = open('compressed_file', 'wb') 
f.write(str_object2) 
f.close() 

Để giải nén một tập tin:

str_object1 = open('compressed_file', 'rb').read() 
str_object2 = zlib.decompress(str_object1) 
f = open('my_recovered_log_file', 'wb') 
f.write(str_object2) 
f.close() 

Ngoài: Tốt hơn để sử dụng các module gzip giúp tiết kiệm bạn phải suy nghĩ về nasssties như chế độ văn bản, đồng chi phí của một vài byte cho thông tin tiêu đề bổ sung.

Nếu bạn đã sử dụng 'rb' và 'wb' trong mã nén nhưng không phải trong mã giải nén [không?], Bạn không bị hosed, bạn chỉ cần xác định mã giải mã ở trên và tìm nó .

Lưu ý cẩn thận việc sử dụng "có thể", "phải", v.v. trong các ý tưởng chưa được kiểm tra sau đây chưa được kiểm tra.

Nếu bạn chưa sử dụng 'rb' và 'wb' trong mã nén của mình, xác suất bạn đã tự đặt mình là khá cao.

Nếu có bất kỳ phiên bản '\ x1a' nào trong tệp gốc của bạn, bất kỳ dữ liệu nào sau lần đầu tiên bị mất - nhưng trong trường hợp đó, không nên thất bại khi giải nén (IOW kịch bản này không khớp với các triệu chứng của bạn).

Nếu một Ctrl-Z được tạo bởi chính zlib, điều này sẽ gây ra một EOF đầu khi cố gắng giải nén, tất nhiên điều này sẽ gây ra một ngoại lệ.Trong trường hợp này, bạn có thể gặt hái ngược lại quy trình bằng cách đọc tệp nén ở chế độ nhị phân và sau đó thay thế '\ r \ n' bằng '\ n' [tức là mô phỏng chế độ văn bản không có Ctrl-Z -> EOF gimmick]. Giải nén kết quả. Chỉnh sửa Viết kết quả ra ở chế độ TEXT. End chỉnh sửa

UPDATE 2 tôi có thể tái tạo các triệu chứng của bạn - với bất kỳ mức 1-9 - với kịch bản sau đây:

import zlib, sys 
fn = sys.argv[1] 
level = int(sys.argv[2]) 
s1 = open(fn).read() # TEXT mode 
s2 = zlib.compress(s1, level) 
f = open(fn + '-ct', 'w') # TEXT mode 
f.write(s2) 
f.close() 
# try to decompress in text mode 
s1 = open(fn + '-ct').read() # TEXT mode 
s2 = zlib.decompress(s1) # error -5 
f = open(fn + '-dtt', 'w') 
f.write(s2) 
f.close() 

Lưu ý: bạn sẽ cần một sử dụng một văn bản hợp lý lớn tệp (Tôi đã sử dụng tệp nguồn 80kb) để đảm bảo rằng kết quả giải nén sẽ chứa '\ x1a'.

tôi có thể phục hồi với kịch bản này:

import zlib, sys 
fn = sys.argv[1] 
# (1) reverse the text-mode write 
# can't use text-mode read as it will stop at Ctrl-Z 
s1 = open(fn, 'rb').read() # BINARY mode 
s1 = s1.replace('\r\n', '\n') 
# (2) reverse the compression 
s2 = zlib.decompress(s1) 
# (3) reverse the text mode read 
f = open(fn + '-fixed', 'w') # TEXT mode 
f.write(s2) 
f.close() 

Chú ý: Nếu có một '\ x1a' aka Ctrl-Z byte trong file gốc, và các tập tin được đọc trong chế độ văn bản, byte mà và tất cả các byte sau sẽ KHÔNG được bao gồm trong tệp nén và do đó KHÔNG thể khôi phục được. Đối với tệp văn bản (ví dụ: mã nguồn), điều này hoàn toàn không mất. Đối với một tệp nhị phân, bạn có nhiều khả năng được ẩn.

Cập nhật 3 [sau mặc khải cuối rằng có một lớp mã hóa/giải mã tham gia vào các vấn đề]:

Các "Lỗi -5" thông điệp chỉ ra rằng dữ liệu mà bạn đang cố gắng để giải nén đã được đọc sai kể từ khi nó được nén. Nếu nó không được gây ra bằng cách sử dụng chế độ văn bản trên các tập tin, nghi ngờ rõ ràng (?) Rơi vào giải mã của bạn và đóng gói mã hóa. Nếu bạn muốn được giúp đỡ, bạn cần tiết lộ nguồn gốc của những trình bao bọc đó. Trong thực tế những gì bạn nên cố gắng làm là (như tôi đã làm) đặt cùng một kịch bản nhỏ mà tái tạo vấn đề trên nhiều hơn một tập tin đầu vào. Thứ hai (như tôi đã làm) xem liệu bạn có thể đảo ngược quy trình trong điều kiện nào không. Nếu bạn muốn trợ giúp với giai đoạn thứ hai, bạn cần tiết lộ kịch bản sinh sản vấn đề.

+2

+1 Câu trả lời rất kỹ lưỡng. Tôi đang gặp vấn đề tương tự, mặc dù bộ đệm không được đọc từ một tập tin, do đó, chế độ nhị phân không phải là một vấn đề. Mặc dù vậy, câu trả lời này là một trợ giúp lớn trong việc hiểu ý nghĩa của lỗi. – DNS

0

OK xin lỗi tôi chưa đủ rõ ràng. Đây là win32, python 2.6.2. Tôi sợ tôi không thể tìm thấy tập tin zlib, nhưng bất cứ điều gì của nó được bao gồm trong bản phát hành nhị phân win32. Và tôi không có quyền truy cập vào dữ liệu gốc - Tôi đã nén các tệp nhật ký của mình và tôi muốn đưa chúng trở lại. Theo như phần mềm khác, tôi đã thử 7zip, nhưng tất nhiên nó không thành công, bởi vì nó là zlib, chứ không phải gzip (tôi không thể giải nén trực tiếp phần mềm zlib). Tôi không thể cung cấp cho một bản sao carbon của traceback bây giờ, nhưng nó đã được (truy trở lại zlib.decompress (dữ liệu)) zlib.error: Lỗi: -3. Ngoài ra, để được rõ ràng, đây là những tập tin tĩnh, không suối như tôi đã làm cho nó âm thanh trước đó (vì vậy không có lỗi truyền dẫn). Và tôi sợ một lần nữa tôi không có mã, nhưng tôi biết tôi đã sử dụng zlib.compress (dữ liệu, 9) (tức là ở mức nén cao nhất - mặc dù, thú vị có vẻ như không phải tất cả đầu ra zlib là 78da bạn có thể mong đợi kể từ khi tôi đặt nó ở mức cao nhất) và chỉ zlib.decompress().

+2

XIN VUI LÒNG chỉnh sửa câu hỏi của bạn để kết hợp các giải thích này. Một số điểm vẫn cần làm rõ: (1) câu hỏi nói lỗi -FIVE, câu trả lời giả nói-BA (2) Tại sao bạn không thể cung cấp một "bản sao carbon" của các traceback bây giờ? Bạn đã xóa các tập tin nén cũng ?? (3) cố gắng nhớ lại những gì mã biến mất của bạn đã làm với đối tượng str trở lại bởi zlib.compress() (4) cố gắng nhớ lại mã giải nén biến mất của bạn thu được một đối tượng str để nạp vào zlib.decompress() –

0

Ok xin lỗi về bài đăng cuối cùng của tôi, tôi không có mọi thứ. Và tôi không thể chỉnh sửa bài đăng của mình vì tôi không sử dụng OpenID.Dù sao, đây là một số dữ liệu:

1) Giải nén traceback: Mã

Traceback (most recent call last): 
    File "<my file>", line 5, in <module> 
    zlib.decompress(data) 
zlib.error: Error -5 while decompressing data 

2) Nén: Mã

#here you can assume the data is the data to be compressed/stored 
data = encrypt(zlib.compress(data,9)) #a short wrapper around PyCrypto AES encryption 
f = open("somefile", 'wb') 
f.write(data) 
f.close() 

3) giải nén:

f = open("somefile", 'rb') 
data = f.read() 
f.close() 

zlib.decompress(decrypt(data)) #this yeilds the error in (1) 
+0

Xem cập nhật của tôi câu trả lời của tôi. –

3

tôi đang tìm kiếm

python -c 'import sys,zlib;sys.stdout.write(zlib.decompress(sys.stdin.read()))' 

tự viết; dựa trên câu trả lời của zlib decompression in python

Các vấn đề liên quan