2009-11-09 33 views

Trả lời

11

Các gzip format quy định cụ thể một lĩnh vực được gọi ISIZE rằng:

This contains the size of the original (uncompressed) input data modulo 2^32.

Trong gzip.py, mà tôi giả định là những gì bạn đang sử dụng để hỗ trợ gzip, có một phương pháp được gọi là _read_eof được định nghĩa là:

def _read_eof(self): 
    # We've read to the end of the file, so we have to rewind in order 
    # to reread the 8 bytes containing the CRC and the file size. 
    # We check the that the computed CRC and size of the 
    # uncompressed data matches the stored values. Note that the size 
    # stored is the true file size mod 2**32. 
    self.fileobj.seek(-8, 1) 
    crc32 = read32(self.fileobj) 
    isize = U32(read32(self.fileobj)) # may exceed 2GB 
    if U32(crc32) != U32(self.crc): 
     raise IOError, "CRC check failed" 
    elif isize != LOWU32(self.size): 
     raise IOError, "Incorrect length of data produced" 

Ở đó bạn có thể thấy rằng trường ISIZE đang được đọc, nhưng chỉ để so sánh nó với self.size để phát hiện lỗi. Điều này có nghĩa là GzipFile.size lưu trữ kích thước không nén thực tế. Tuy nhiên, tôi nghĩ rằng nó không được hiển thị công khai, vì vậy bạn có thể phải hack nó để lộ nó. Không chắc lắm, xin lỗi.

Tôi chỉ xem tất cả những điều này ngay bây giờ và tôi chưa thử nó để tôi có thể sai. Tôi hy vọng đây là một số sử dụng cho bạn. Xin lỗi nếu tôi hiểu lầm câu hỏi của bạn.

+0

Tôi đoán điều này là đủ tốt. Trong trường hợp tệp lớn hơn 4G, bạn có thể dễ dàng thêm một số phỏng đoán vào thanh tiến trình để đặt kích thước tệp thành 4G + ISIZE, nếu tell() cho biết chúng tôi quá gần với ISIZE. –

+0

Tôi cần phải làm điều tương tự và tôi đang cố gắng mở rộng lớp GzipFile để cung cấp kích thước tệp, nhưng tôi không thành công, Bạn làm cách nào để nó hoạt động? – lanrat

+0

Cập nhật: Chức năng này hoạt động cho tôi: http://code.activestate.com/lists/python-list/245777/ – lanrat

4

Cách Unix: sử dụng "gunzip -l file.gz" qua subprocess.call/os.popen, chụp và phân tích đầu ra của nó.

+0

Không bao giờ chạm vào hệ điều hành cũ hơn tôi ... Nói nghiêm túc: Tôi đang tìm giải pháp python, vì mã dành cho tất cả các nền tảng. –

+2

Windows ít nhất là 24 hoặc 25 tuổi. Phiên bản 1 xuất hiện vào khoảng năm 1985 hoặc lâu hơn. Bạn bao nhiêu tuổi? – jmucchiello

+0

44.5 (và được sử dụng lần cuối là Unix tại 18) –

0

Nhìn vào nguồn cho mô-đun gzip, tôi thấy rằng đối tượng tệp cơ bản cho GzipFile có vẻ là fileobj. Vì vậy:

mygzipfile = gzip.GzipFile() 
... 
mygzipfile.fileobj.tell() 

?

Có thể bạn nên kiểm tra sự tỉnh táo trước khi thực hiện điều đó, như kiểm tra xem thuộc tính có tồn tại với hasattr hay không.

Không chính xác một API công cộng, nhưng ...

+0

.tell() hoạt động tốt. Những gì tôi đang tìm kiếm là kích thước tệp gốc. –

+0

không phải mygzipfile.tell(), thay vào đó là mygzipfile.fileobj.tell(). –

4

4 byte cuối cùng của gz giữ kích thước ban đầu của tập tin

+3

4 byte cuối cùng là “kích thước của dữ liệu đầu vào ban đầu (không nén) modulo 2^32.” (Http://www.gzip.org/zlib/rfc-gzip.html) – Gumbo

0

GzipFile.size lưu trữ kích thước không nén, nhưng nó chỉ tăng lên khi bạn đọc tệp, vì vậy bạn nên thích len (fd.read()) thay vì GzipFile.size không công khai.

+0

Điều gì xảy ra nếu tệp lớn? – allyourcode

+0

@allyourcode: Chờ lâu hơn :) – quetzalcoatl

1
f = gzip.open(filename) 
    # kludge - report uncompressed file position so progess bars 
    # don't go to 400% 
    f.tell = f.fileobj.tell 
-2
import gzip 

File = gzip.open("input.gz", "r") 
Size = gzip.read32(File) 
12

kích thước không nén được lưu trữ trong 4 byte cuối cùng của file gzip. Chúng ta có thể đọc dữ liệu nhị phân và chuyển đổi nó thành một int. (Điều này sẽ chỉ làm việc cho các tập tin dưới 4GB)

import struct 

def getuncompressedsize(filename): 
    with open(filename, 'rb') as f: 
     f.seek(-4, 2) 
     return struct.unpack('I', f.read(4))[0] 
+0

Mở tệp '" rb "' để tránh 'lỗi: giải nén yêu cầu đối số chuỗi có độ dài 4'. – slv

+0

Đây chính xác là những gì được hiển thị trong câu trả lời cũ ** Jorge Israel Peña **, do đó, trong khi câu trả lời của bạn cung cấp một chức năng tiện dụng, nó không thêm nhiều vào chủ đề. Hơn nữa, như ý kiến ​​nói trong câu trả lời cũ, chỉ phụ thuộc vào 4 byte cuối cùng thực sự là không 100% dễ dàng, như GZ cho phép bạn chắp thêm khối mới vào cuối tập tin – quetzalcoatl

1

Tôi không chắc chắn về hiệu suất, nhưng điều này có thể đạt được mà không biết gzip ma thuật bằng cách sử dụng:

with gzip.open(filepath, 'rb') as file_obj: 
    file_size = file_obj.seek(0, io.SEEK_END) 

này cũng nên làm việc cho khác (nén) luồng độc giả như bz2 hoặc đồng bằng open.

EDIT: như được đề xuất trong các nhận xét, 2 trong dòng thứ hai được thay thế bằng io.SEEK_END, điều này chắc chắn dễ đọc hơn và có thể là tương lai hơn.

+0

tức là 'file_size = file_obj.seek (0, io. SEEK_END) ' – user3780389

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