2013-11-22 3 views
0

У меня есть много архива zip с текстовыми файлами в них. Мне нужно найти и изменить определенный текст в файлах. Тем не менее, мне удалось найти все соответствующие строки в файлах с использованием:Редактирование содержимого файла внутри zip-файла

import os 
import zipfile 
from glob import glob 

files = [] 
pattern = "*.zip" 
for dir,_,_ in os.walk(r'X:\zips'): 
    files.extend(glob(os.path.join(dir,pattern))) 

    for file in files: 
     root = zipfile.ZipFile(file, "r") 
     for name in root.namelist(): 
      for line in root.read(name).split("\n"): 
       if line.find("keyword") >= 0: 
        print line 

Я знаю, что я могу заменить ключевое слово в строке. Но как я могу сохранить его «inplace», не записывая все другие текстовые файлы на hdd, удаляя старый zip и создавая новый?

+0

Что вы пробовали? Пробовали ли вы открыть файл с режимом '' a'' и вызывать 'root.write()'? –

ответ

4

Вы не можете сделать это, не делая бизнес обезьяны низкого уровня, который, возможно, не поддерживается из коробки с помощью модуля zipfile. Однако это возможно.

Первое быстрое объяснение структуры ZIP файла:

От PKWare's ZIP file structure document

[local file header 1] 
    [encryption header 1] 
    [file data 1] 
    [data descriptor 1] 
    . 
    . 
    . 
    [local file header n] 
    [encryption header n] 
    [file data n] 
    [data descriptor n] 
    [archive decryption header] 
    [archive extra data record] 
    [central directory header 1] 
    . 
    . 
    . 
    [central directory header n] 
    [zip64 end of central directory record] 
    [zip64 end of central directory locator] 
    [end of central directory record] 

Заголовок файла выглядит следующим образом:

local file header signature  4 bytes (0x04034b50) 
    version needed to extract  2 bytes 
    general purpose bit flag  2 bytes 
    compression method    2 bytes 
    last mod file time    2 bytes 
    last mod file date    2 bytes 
    crc-32       4 bytes 
    compressed size     4 bytes 
    uncompressed size    4 bytes 
    file name length    2 bytes 
    extra field length    2 bytes 

    file name (variable size) 
    extra field (variable size) 

Центральная структура каталогов выглядит следующим образом:

central file header signature 4 bytes (0x02014b50) 
    version made by     2 bytes 
    version needed to extract  2 bytes 
    general purpose bit flag  2 bytes 
    compression method    2 bytes 
    last mod file time    2 bytes 
    last mod file date    2 bytes 
    crc-32       4 bytes 
    compressed size     4 bytes 
    uncompressed size    4 bytes 
    file name length    2 bytes 
    extra field length    2 bytes 
    file comment length    2 bytes 
    disk number start    2 bytes 
    internal file attributes  2 bytes 
    external file attributes  4 bytes 
    relative offset of local header 4 bytes 

    file name (variable size) 
    extra field (variable size) 
    file comment (variable size) 

В каждом файле есть CRC и размер для каждого файла, а также CRC и размер в центральном каталоге. Таким образом, для изменения одного файла - в зависимости от того, что вы на самом деле делаете с этим файлом, размер файла будет, скорее всего, изменяться, и CRC также будет 99% изменения времени.

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

Вы можете работать вокруг этого НЕ сжатия, что конкретный файл - КПР изменится, но общий размер файла не будет (до тех пор, пока вы сохраняете в границах этого единого файла

Вы будете в. по крайней мере, однако необходимо:

  1. обновить файл CRC
  2. Обновление CRC центрального каталога файлов

Стоит отметить, что центральный каталог, находящийся в конце файла, является своеобразной опрятной функцией - поскольку это означает, что вы можете генерировать «динамические» zip-файлы на лету. Я сделал это некоторое время назад для компании, которая продавала MP3 в Интернете, я сделал «динамический» почтовый пакет, который по существу объединил бы файлы MP3 вместе с правыми ZIP-заголовками, чтобы вы могли добавить кучу песен в «список загрузки», , который будет передавать MP3-файлы из их домов на диск непосредственно клиенту - вводит правильную информацию заголовка и, наконец, центральную запись каталога - со стороны веб-сервера она просто была серией чтения и записи, но на клиенте она выглядела как «реальный» zip-файл.

+0

Хорошо, что кажется сложнее, чем я ожидал. Может быть, я должен просто извлечь все файлы в временную папку, удалить старый zip, заменить текст в конкретном файле и сохранить новый zip со старым именем – W0bble

+0

Ну, это возможно с помощью zipfile-модуля, но это будет связано с связкой дискового оттока. Вам в основном придется удалить файл из архива (churn) и добавить новый файл (отбой).Вы можете использовать StringIO, чтобы делать это в памяти, если это небольшой файл, но я бы не рекомендовал его в качестве общей практики, поскольку он не масштабируется исключительно хорошо. Если у вас есть контроль над форматом (т. Е. Вы можете переключиться на другой формат?), Вы можете посмотреть формат потокового архива, такой как tar или cpio. – synthesizerpatel

+0

К сожалению, я не контролирую структуру данных. Я проверю параметры, связанные с StringIO или cStringIO – W0bble

Смежные вопросы