在Python中解压.bz2文件
这看起来是个简单的问题,但我似乎有点笨。我有一个小脚本,可以从网页上下载所有的 .bz2 文件,但解压这个文件让我头疼得厉害。
我还是个 Python 新手,所以答案可能很明显,请帮帮我。
在这个脚本的部分,我已经有了文件,我只想把它读到一个变量里,然后解压,这样对吗?我试过各种方法,通常在这段代码的最后一行会出现“ValueError: couldn't find end of stream”的错误。我尝试打开压缩文件并用无数种方法写入字符串。这是我最新的尝试。
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() 的方式。
方法 A:
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 手动解压了一下,确保文件没有问题,结果解压得很好。
3 个回答
这段话很有帮助。
在2300个文件中,有44个文件在Windows上打开时出现了“文件结尾缺失”的错误。
在打开文件时加上b(表示二进制)这个标志解决了这个问题。
for line in bz2.BZ2File(filename, 'rb', 10000000) :
效果很好。(10M是适合处理大文件的缓冲区大小)
谢谢!
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)
如果这样还不行,我认为可能是上面提到的换行符转换问题导致的。
你正在打开和读取一个压缩文件,就像它是一个由行组成的文本文件一样。别这样!它不是。
uncompressedData = bz2.BZ2File(zipFile).read()
这看起来更接近你想要的。
补充说明:提问者展示了一些他尝试过的方法(虽然我没看到他尝试过我上面推荐的最佳方法——那条一行代码!),但他们似乎都有一个共同的错误,我再重复一下关键点:
打开压缩文件时,像对待文本文件一样……它不是。
open(filename)
,甚至更明确的 open(filename, 'r')
,都是用来打开文本文件的——而压缩文件是二进制文件,所以为了正确读取它,你必须用 open(filename, 'rb')
来打开它。((我推荐的 bz2.BZ2File
自然知道它在处理一个压缩文件,所以不需要告诉它更多信息)).
在 Python 2.*
中,在类 Unix 系统(也就是除了 Windows 以外的所有系统)上,你可以随便用 open
(但在 Python 3.*
中就不行了,因为文本是 Unicode,而二进制是字节——这两者是不同的类型)。
在 Windows(以及之前的 DOS)中,区分这两者一直是非常重要的,因为历史原因,Windows 的文本文件是特殊的(使用两个字节而不是一个字节来结束行,并且在某些情况下,把一个字节的 '\0x1A'
视为逻辑上的文件结束),所以读取和写入的底层代码必须进行补偿。
所以我怀疑提问者在使用 Windows,并且因为没有仔细使用 'rb'
选项(“读取二进制”)来打开文件而付出了代价。(不过无论你使用什么平台,bz2.BZ2File
仍然更简单!)