在Python中解压.bz2文件

7 投票
3 回答
15489 浏览
提问于 2025-04-15 13:28

这看起来是个简单的问题,但我似乎有点笨。我有一个小脚本,可以从网页上下载所有的 .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 个回答

6

这段话很有帮助。

在2300个文件中,有44个文件在Windows上打开时出现了“文件结尾缺失”的错误。

在打开文件时加上b(表示二进制)这个标志解决了这个问题。

for line in bz2.BZ2File(filename, 'rb', 10000000) :

效果很好。(10M是适合处理大文件的缓冲区大小)

谢谢!

9

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)

如果这样还不行,我认为可能是上面提到的换行符转换问题导致的。

16

你正在打开和读取一个压缩文件,就像它是一个由行组成的文本文件一样。别这样!它不是。

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 仍然更简单!)

撰写回答