[英]How to tell if a file is gzip compressed?
我有一個 Python 程序,它將把文本文件作為輸入。 但是,其中一些文件可能是 gzip 壓縮的。
是否有跨平台的、可從 Python 使用的方式來確定文件是否是 gzip 壓縮的?
以下是可靠的還是普通的文本文件“不小心”看起來像 gzip 一樣足以讓我得到誤報?
try:
gzip.GzipFile(filename, 'r')
# compressed
# ...
except:
# not compressed
# ...
gzip 壓縮文件的幻數是1f 8b
。 盡管對此進行的測試不是 100% 可靠,但“普通文本文件”極不可能以這兩個字節開頭——在 UTF-8 中它甚至是不合法的。
不過,通常 gzip 壓縮文件的后綴是.gz
。 甚至gzip(1)
本身也不會在沒有它的情況下解壓縮文件,除非您--force
它。 您可以想象使用它,但您仍然必須處理可能的 IOError (無論如何您都必須這樣做)。
您的方法的一個問題是,如果您提供一個未壓縮的文件, gzip.GzipFile()
不會引發異常。 只有稍后read()
才會。 這意味着,您可能必須兩次實現某些程序邏輯。 丑。
是否有跨平台的、可從 Python 使用的方式來確定文件是否是 gzip 壓縮的?
接受的答案解釋了一般如何檢測 gzip 壓縮文件:測試前兩個字節是否為1f 8b
。 但是它沒有展示如何在 Python 中實現它。
這是一種方法:
def is_gz_file(filepath):
with open(filepath, 'rb') as test_f:
return test_f.read(2) == b'\x1f\x8b'
測試 gzip 文件的幻數是唯一可靠的方法。 但是,從 python3.7 開始,不再需要自己比較字節。 gzip 模塊將為您比較字節,如果不匹配則引發異常!
從python3.7開始,這有效
import gzip
with gzip.open(input_file, 'r') as fh:
try:
fh.read(1)
except OSError:
print('input_file is not a valid gzip file by OSError')
從 python3.8 開始,這也有效:
import gzip
with gzip.open(input_file, 'r') as fh:
try:
fh.read(1)
except gzip.BadGzipFile:
print('input_file is not a valid gzip file by BadGzipFile')
gzip
本身將引發OSError
如果它不是一個壓縮文件。
>>> with gzip.open('README.md', 'rb') as f:
... f.read()
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 276, in read
return self._buffer.read(size)
File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 463, in read
if not self._read_gzip_header():
File "/Users/dennis/.asdf/installs/python/3.6.6/lib/python3.6/gzip.py", line 411, in _read_gzip_header
raise OSError('Not a gzipped file (%r)' % magic)
OSError: Not a gzipped file (b'# ')
可以將此方法與其他一些方法結合使用以增加信心,例如檢查 mimetype 或在文件頭中查找幻數(請參閱其他答案的示例)並檢查擴展名。
import pathlib
if '.gz' in pathlib.Path(filepath).suffixes:
# some more inexpensive checks until confident we can attempt to decompress
# ...
try ...
...
except OSError as e:
...
導入mimetypes模塊。 它可以自動猜測您擁有什么樣的文件,以及它是否被壓縮。
即
mimetypes.guess_type('blabla.txt.gz')
返回:
('文本/純文本', 'gzip')
在python3中似乎不太好用...
import mimetypes
filename = "./datasets/test"
def file_type(filename):
type = mimetypes.guess_type(filename)
return type
print(file_type(filename))
返回 (None, None) 但是來自 unix 命令“文件”
:~> 文件數據集/測試數據集/測試:gzip 壓縮數據,是“iostat_collection”,來自 Unix,最后修改時間:2015 年 1 月 29 日星期四 07:09:34
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.