在 Python 中解压缩 .bz2 文件
Posted
技术标签:
【中文标题】在 Python 中解压缩 .bz2 文件【英文标题】:Decompressing a .bz2 file in Python 【发布时间】:2009-08-09 05:01:42 【问题描述】:所以,这是一个看似简单的问题,但我显然非常非常沉闷。我有一个从网页下载所有 .bz2 文件的小脚本,但由于某种原因,该文件的解压缩让我非常头疼。
我是一个Python新手,所以答案可能很明显,请帮助我。
在这部分脚本中,我已经有了文件,我只想将它读出到一个变量中,然后解压缩?是对的吗?我已经尝试了各种方法来做到这一点,我通常在这个 sn-p 的最后一行得到“ValueError:找不到流的结尾”错误。我试图打开 zipfile 并以无数种不同的方式将其写入字符串。这是最新的。
openZip = open(zipFile, "r")
s = ''
while True:
newLine = openZip.readline()
if(len(newLine)==0):
break
s+=newLine
print s
uncompressedData = bz2.decompress(s)
嗨,Alex,我应该列出我尝试过的所有其他方法,因为我尝试过 read() 方式。
方法一:
print 'decompressing ' + filename
fileHandle = open(zipFile)
uncompressedData = ''
while True:
s = fileHandle.read(1024)
if not s:
break
print('RAW "%s"', s)
uncompressedData += bz2.decompress(s)
uncompressedData += bz2.flush()
newFile = open(steamTF2mapdir + filename.split(".bz2")[0],"w")
newFile.write(uncompressedData)
newFile.close()
我得到错误:
uncompressedData += bz2.decompress(s)
ValueError: couldn't find end of stream
方法 B
zipFile = steamTF2mapdir + filename
print 'decompressing ' + filename
fileHandle = open(zipFile)
s = fileHandle.read()
uncompressedData = bz2.decompress(s)
同样的错误:
uncompressedData = bz2.decompress(s)
ValueError: couldn't find end of stream
非常感谢您的及时回复。我真的把我的头撞在墙上,因为无法解压缩一个简单的 .bz2 文件而感到非常沉重。
顺便说一句,使用7zip手动解压,以确保文件没有问题或任何东西,并且解压正常。
【问题讨论】:
你真的尝试过 Alex 的建议吗? 【参考方案1】:您正在打开和读取压缩文件,就像它是由行组成的文本文件一样。不!不是。
uncompressedData = bz2.BZ2File(zipFile).read()
似乎更接近您的目标。
编辑:OP 展示了他尝试过的更多东西(尽管我没有看到任何关于尝试过最佳方法的说明——我在上面推荐的单线!)但他们似乎都有一个共同点,我重复上面的关键位:
打开...压缩文件好像 它是一个文本文件......它不是。
open(filename)
甚至更明确的open(filename, 'r')
打开并读取一个文本文件——压缩文件是一个二进制文件,所以为了正确阅读它,您必须使用open(filename, 'rb')
打开它。 (((我推荐的bz2.BZ2File
当然知道它在处理压缩文件,所以没有必要再告诉它)。
在 Python 2.*
中,在 Unix-y 系统(即除 Windows 之外的所有系统)中,您可以随意使用 open
(但在 Python 3.*
中则不能,因为文本是 Unicode , 而二进制是字节——不同的类型)。
在 Windows 中(以及在此之前的 DOS 中),区分始终是必不可少的,因为 Windows 的文本文件由于历史原因是特殊的(使用两个字节而不是一个字节来结束行,并且至少在某些情况下,取一个值'\0x1A'
的字节作为文件的逻辑结尾),所以读写低级代码必须补偿。
所以我怀疑 OP 正在使用 Windows,并且正在为不小心使用 'rb'
选项(“读取二进制”)到内置的 open
付出代价。 (尽管bz2.BZ2File
仍然更简单,无论您使用什么平台!-)。
【讨论】:
嗨,Alex,感谢您的快速回复,请查看我的问题中针对您的评论进行的编辑。 所以这个方法的问题是,虽然它似乎解压得很好,但当我尝试运行它时,文件不知何故损坏了。当我使用 7zip 打开 .bz2 文件时,它运行良好。此外,正确提取的文件(使用 7zip)的大小为 948kb,而从我的脚本中提取的文件为 952KB。我完全感到困惑。 7zip 接受除 bz2 之外的许多其他格式,也许您的文件是其他格式之一。如果法律和隐私不妨碍这样做,把它放在一个公共 URL 上,给我 URL,我会让你知道它是什么格式以及如何解码它——没有手头的文件,基本上就是这样我做不到。 感谢您的所有帮助,Alex,抱歉在这里有点厚。这是有道理的,但是为什么 python bz2 库会解压缩文件呢?它不会抛出某种异常吗?我看看能不能找到放文件的地方(这不是违法的,它只是一个Team Fortress2地图文件(.bsp文件)的.bz2文件,但我不想把URL公开,因为它是我朋友的服务器托管它。如何检查 .bz2 文件是否实际上在 bz2 文件中? 但你说它确实引发了异常——ValueError!我相信你可以在bzip.org/downloads.html 下载一个仅限 bzip2 的可执行文件——如果该 exe 正确解码文件,我相信这应该证明它是一个 .bz2,反之亦然。【参考方案2】:openZip = open(zipFile, "r")
如果您在 Windows 上运行,您可能需要在此处输入 openZip = open(zipFile, "rb"),因为该文件可能包含 CR/LF 组合,而您不需要'不希望他们被翻译。
newLine = openZip.readline()
正如 Alex 指出的那样,这是非常错误的,因为“行”的概念对于压缩流来说是陌生的。
s = fileHandle.read(1024) [...] uncompressedData += bz2.decompress(s)
出于同样的原因,这是错误的。 1024 字节的块对解压器来说意义不大,因为它需要使用自己的块大小。
s = fileHandle.read() uncompressedData = bz2.decompress(s)
如果不行,我会说是我上面提到的换行翻译问题。
【讨论】:
谢谢,这很有帮助。【参考方案3】:这很有帮助。 在 Windows 打开时,2300 个文件中有 44 个给出了文件结尾丢失错误。 添加 b(inary) 标志来打开解决了这个问题。
for line in bz2.BZ2File(filename, 'rb', 10000000) :
效果很好。 (10M 是缓冲大小,适用于所涉及的大文件)
谢谢!
【讨论】:
以上是关于在 Python 中解压缩 .bz2 文件的主要内容,如果未能解决你的问题,请参考以下文章
AWS Lambda (Python) 无法在 S3 中解压缩和存储文件
如何在 Python3 中解压缩使用 PKZIP 以外的算法加密的文件?