Python gzip refuses to read uncompressed file

前端 未结 4 1668
一整个雨季
一整个雨季 2021-01-17 13:31

I seem to remember that the Python gzip module previously allowed you to read non-gzipped files transparently. This was really useful, as it allowed to read an input file wh

相关标签:
4条回答
  • 2021-01-17 14:14

    Read the first four bytes. If the first three are 0x1f, 0x8b, 0x08, and if the high three bits of the fourth byte are zeros, then fire up the gzip compression starting with those four bytes. Otherwise write out the four bytes and continue to read transparently.

    You should still have the clunky solution to back that up, so that if the gzip read fails nevertheless, then back up and read transparently. But it should be quite unlikely to have the first four bytes mimic a gzip file so well, but not be a gzip file.

    0 讨论(0)
  • 2021-01-17 14:22

    Maybe you're thinking of zless or zgrep, which will open compressed or uncompressed files without complaining.

    Can you trust that the file name ends in .gz?

    if file_name.endswith('.gz'):
        opener = gzip.open
    else:
        opener = open
    
    with opener(file_name, 'r') as f:
        ...
    
    0 讨论(0)
  • 2021-01-17 14:25

    The best solution for this would be to use something like https://github.com/ahupp/python-magic with libmagic. You simply cannot avoid at least reading a header to identify a file (unless you implicitly trust file extensions)

    If you're feeling spartan the magic number for identifying gzip(1) files is the first two bytes being 0x1f 0x8b.

    In [1]: f = open('foo.html.gz')
    In [2]: print `f.read(2)`
    '\x1f\x8b'
    

    gzip.open is just a wrapper around GzipFile, you could have a function like this that just returns the correct type of object depending on what the source is without having to open the file twice:

    #!/usr/bin/python
    
    import gzip
    
    def opener(filename):
        f = open(filename,'rb')
        if (f.read(2) == '\x1f\x8b'):
            f.seek(0)
            return gzip.GzipFile(fileobj=f)
        else:
            f.seek(0)
            return f
    
    0 讨论(0)
  • 2021-01-17 14:27

    You can iterate over files transparently using fileinput(files, openhook=fileinput.hook_compressed)

    0 讨论(0)
提交回复
热议问题