Распаковка файла .bz2 в Python - PullRequest
6 голосов
/ 09 августа 2009

Итак, это, казалось бы, простой вопрос, но я, очевидно, очень и очень скучный. У меня есть небольшой скрипт, который загружает все файлы .bz2 с веб-страницы, но по какой-то причине распаковка этого файла вызывает у меня ОСНОВНУЮ головную боль.

Я довольно новичок в Python, поэтому ответ, вероятно, вполне очевиден, пожалуйста, помогите мне.

В этом фрагменте сценария у меня уже есть файл, и я просто хочу прочитать его в переменной, а затем распаковать его? Это правильно? Я пробовал все виды способов сделать это, я обычно получаю сообщение об ошибке «ValueError: не удалось найти конец потока» в последней строке этого фрагмента. Я попытался открыть zip-файл и записать его в строку разными способами. Это самое последнее.

openZip = open(zipFile, "r")
s = ''
while True:
    newLine = openZip.readline()
    if(len(newLine)==0):
       break
    s+=newLine
    print s                   
    uncompressedData = bz2.decompress(s)

Привет, Алекс, мне следовало перечислить все другие методы, которые я пробовал, так как я пробовал метод 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 ]

14 голосов
/ 09 августа 2009

Вы открываете и читаете сжатый файл, как если бы это был текстовый файл, состоящий из строк. DO NOT! Это НЕ.

uncompressedData = bz2.BZ2File(zipFile).read()

кажется, ближе к тому, за что ты ловишь рыбу.

Редактировать : ОП показал еще несколько вещей, которые он пробовал (хотя я не вижу никаких замечаний о том, что попробовал лучший метод - одну строчку, которую я рекомендую выше!), Но они кажутся у всех одна общая ошибка, и я повторяю биты ключей сверху:

открытие ... сжатый файл как будто это был текстовый файл ... Это НЕ.

open(filename) и даже более явный open(filename, 'r') открытый для чтения файл text - сжатый файл представляет собой двоичный файл , поэтому для его чтения правильно вы должны открыть его с помощью open(filename, 'rb'). ((мой рекомендованный bz2.BZ2File ЗНАЕТ, что он имеет дело со сжатым файлом, разумеется, поэтому больше не нужно ничего рассказывать)).

В Python 2.*, в системах Unix-y (то есть в каждой системе, кроме Windows), вы можете избежать небрежного использования open (но в Python 3.* вы не можете, так как текст в Unicode , в то время как двоичные - это байты - разные типы).

В Windows (и до этого в DOS) всегда было необходимо различать, поскольку текстовые файлы Windows по исторической причине являются своеобразными (используйте два байта, а не один, чтобы завершить строки, и, по крайней мере, в некоторых случаях, принять значение байта '\0x1A' как логическое окончание файла), поэтому чтение и запись низкоуровневого кода должны компенсировать это.

Так что я подозреваю, что OP использует Windows и платит цену за то, что не осторожно использовал опцию 'rb' («читать двоичный файл») для встроенного open. (хотя bz2.BZ2File все еще проще, какую бы платформу вы не использовали! -).

9 голосов
/ 09 августа 2009

openZip = open (zipFile, "r")

Если вы работаете в Windows, вы можете сказать openZip = open (zipFile, "rb") здесь, так как файл, скорее всего, содержит комбинации CR / LF, а вы не Я не хочу, чтобы они были переведены.

newLine = openZip.readline ()

Как указал Алекс, это очень неправильно, поскольку понятие "линии" чуждо сжатому потоку.

s = fileHandle.read (1024) [...] uncompressedData + = bz2.decompress (s)

Это неправильно по той же причине. 1024-байтовые блоки вряд ли что-то значат для декомпрессора, так как он захочет работать со своим собственным размером блока.

s = fileHandle.read () uncompressedData = bz2.decompress (s)

Если это не сработает, я бы сказал, что это проблема перевода с новой строки, о которой я упоминал выше.

5 голосов
/ 03 сентября 2010

Это было очень полезно. 44 из 2300 файлов выдавали ошибку об отсутствии файла при открытии Windows. Добавление флага b (inary) для открытия исправило проблему.

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

работает хорошо. (10M - это размер буфера, который хорошо работает с большими файлами)

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...