在不完全提取的情况下读取 tarfile 中的大文件头 (~9GB)

Read large file header (~9GB) inside tarfile without full extraction

我有 ~1GB *.tbz 文件。在这些文件中的每一个中,都有一个大约 9GB 的文件。我只需要读取这个文件的头,前 1024 个字节。

我希望它尽可能快地执行此操作,因为我有数百个要处理的 1GB 文件。提取大约需要 1 分 30 秒。

我尝试使用完全提取:

tar = tarfile.open(fn, mode='r|bz2')
for item in tar:
    tar.extract(item)

tarfile.getmembers()但没有速度改进:

tar = tarfile.open(fn, mode='r|bz2')
for member in tar.getmembers():
    f = tar.extractfile(member)
    headerbytes = f.read(1024)
    headerdict = parseHeader(headerbytes)

getmembers() 方法一直在那里。

有什么办法吗?

如果您确定每个 tar 存档只包含一个 bz2 文件,您可以在第一次读取 tar 文件时跳过前 512 个字节(不是包含的 bz2 文件当然,在其中),因为 tar 文件格式有一个填充(固定大小)header,之后您的 "real" 内容被存储。

一个简单的

f.seek(512)

而不是遍历 getmembers() 应该可以做到这一点。

我认为你应该使用标准库 bz2 接口。 .tbztar 文件的文件扩展名,这些文件使用 -j 选项压缩以指定 bzip2 格式。

作为 @bbayles pointed out in the comments, you can open your file as a bz2.BZ2File 并使用 seekread:

read([size])

Read at most size uncompressed bytes, returned as a string. If the size argument is negative or omitted, read until EOF is reached.

seek(offset[, whence])

Move to new file position. Argument offset is a byte count.

f = bz2.BZ2File(path)
f.seek(512) 
headerbytes = f.read(1024)

然后您可以使用您的函数对其进行解析。

headerdict = parseHeader(headerbytes)