如何列出gz文件的内容而不在python中进行解压缩?
我有一个如何列出gz文件的内容而不在python中进行解压缩?,python,compression,gzip,extraction,Python,Compression,Gzip,Extraction,我有一个.gz文件,需要使用python获取其中的文件名 这个问题与 唯一的区别是我的文件是.gz而不是.tar.gz,所以tarfile库在这里对我没有帮助 我正在使用请求库请求URL。响应是一个压缩文件 这是我用来下载文件的代码 response = requests.get(line.rstrip(), stream=True) if response.status_code == 200: with open(str(base_output_dir
.gz
文件,需要使用python获取其中的文件名
这个问题与
唯一的区别是我的文件是.gz
而不是.tar.gz
,所以tarfile
库在这里对我没有帮助
我正在使用请求
库请求URL。响应是一个压缩文件
这是我用来下载文件的代码
response = requests.get(line.rstrip(), stream=True)
if response.status_code == 200:
with open(str(base_output_dir)+"/"+str(current_dir)+"/"+str(count)+".gz", 'wb') as out_file:
shutil.copyfileobj(response.raw, out_file)
del response
例如,此代码下载名为1.gz
的文件。现在,如果我使用归档管理器打开文件,文件将包含类似于my_latest_data.json
我需要提取文件,输出为my\u latest\u data.json
下面是我用来提取文件的代码
inF = gzip.open(f, 'rb')
outfilename = f.split(".")[0]
outF = open(outfilename, 'wb')
outF.write(inF.read())
inF.close()
outF.close()
outputfilename
变量是我在脚本中提供的字符串,但我需要真实的文件名(my\u latest\u data.json
),因为Gzip不是存档格式
这本身就是一个有点垃圾的解释,所以让我比在评论中更详细地解释一下
它只是压缩
“只是一个压缩系统”意味着Gzip操作输入字节(通常来自文件)并输出压缩字节。您无法知道其中的字节是表示多个文件还是仅表示一个文件——它只是一个已压缩的字节流。例如,这就是为什么可以通过网络接受gzip数据。它的bytes\u in->bytes\u out
什么是舱单?
清单是存档中的标头,用作存档的目录。请注意,现在我使用的是术语“归档”,而不是“压缩的字节流”。存档意味着它是清单引用的文件或段的集合——压缩的字节流就是字节流
Gzip里面到底是什么?
对.gz文件内容的简化描述如下:
.tar.gz
非常普遍
有一些实用程序允许您一次解压缩gzip文件的一部分,或者只在内存中解压缩它,然后让您检查清单或其中可能包含的任何内容。但是任何清单的详细信息都是特定于其中包含的归档格式的
请注意,这与zip归档不同。Zip是一种存档格式,因此包含清单。Gzip是一个压缩库,就像bzip2和friends一样。如另一个答案中所述,您的问题只有在去掉复数形式后才有意义:“我有一个
.gz
文件,我需要使用python获取其中的文件名。”
gzip头中可能有文件名,也可能没有文件名。gzip实用程序通常会忽略标题中的名称,并解压缩到一个与.gz
文件同名的文件中,但将.gz
剥离。例如,您的1.gz
将解压缩为名为1
的文件,即使标题中包含文件名my_latest_data.json
。gzip的-N选项将使用头中的文件名(以及头中的时间戳)(如果有)。因此gzip-dn1.gz
将创建文件my_latest_data.json
,而不是1
在Python中,可以通过手动处理头文件在头文件中找到文件名。您可以在中找到详细信息
1f 8b 08
标志
。如果flags&8
为零,则放弃——头中没有文件名标志&2
不是零,则跳过两个字节标志&4
不是零,则读取下两个字节。考虑到它们是以小尾端顺序排列的,从这两个字节中取一个整数,称之为xlen
。然后跳过xlen
字节flags&8
不是零,因此您现在在文件名处。读取字节,直到达到零字节。这些字节(不包括零字节)是文件名注意:这个答案在Python 3中已经过时了
使用MarkAdler回复中的提示和对gzip模块的一些检查,我设置了这个函数,从gzip文件中提取内部文件名。我注意到GzipFile对象有一个名为_read_gzip_header()的私有方法,它几乎可以获取文件名,所以我就是基于这个方法来做的
import gzip
def get_gzip_filename(filepath):
f = gzip.open(filepath)
f._read_gzip_header()
f.fileobj.seek(0)
f.fileobj.read(3)
flag = ord(f.fileobj.read(1))
mtime = gzip.read32(f.fileobj)
f.fileobj.read(2)
if flag & gzip.FEXTRA:
# Read & discard the extra field, if present
xlen = ord(f.fileobj.read(1))
xlen = xlen + 256*ord(f.fileobj.read(1))
f.fileobj.read(xlen)
filename = ''
if flag & gzip.FNAME:
while True:
s = f.fileobj.read(1)
if not s or s=='\000':
break
else:
filename += s
return filename or None
但是您可以采用链接周围的代码来使用它做其他事情
如本页其他答案所述,此信息是可选的。但是,如果你需要查看它是否在那里,就不可能找回它
导入结构
def gzinfo(文件名):
#从gzip.py第16行复制并粘贴
FTEXT,FHCRC,FEXTRA,FNAME,FCOMMENT=1,2,4,8,16
以fp形式打开(文件名为“rb”):
#基本上是从GzipFile模块行429f复制+粘贴
魔法=fp.read(2)
如果magic==b“”:
返回错误
如果有魔法!=b'\037\213':
raise VALUERROR('不是gzip文件(%r)')%magic