编辑 zip 文件中文件的内容

W0b*_*ble 0 python io 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
Run Code Online (Sandbox Code Playgroud)

我知道我可以替换行内的关键字。但是如何在不将所有其他文本文件写入硬盘的情况下“就地”保存它,删除旧的 zip 并创建一个新的 zip 文件?

syn*_*tel 5

如果不做一些可能不受 zipfile 模块开箱即用的低级猴子业务,您就无法做到这一点。然而,这是可能的。

首先快速解释一下 ZIP 文件结构:

来自PKWare 的 ZIP 文件结构文档

  [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]
Run Code Online (Sandbox Code Playgroud)

文件头如下所示:

  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)
Run Code Online (Sandbox Code Playgroud)

中央目录结构如下所示:

    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)
Run Code Online (Sandbox Code Playgroud)

每个文件都有每个文件的 CRC 和大小,中央目录中有一个 CRC 和大小。因此,要修改单个文件 - 根据您对该文件的实际操作,文件大小很可能会发生变化,并且 CRC 也会在 99% 的情况下发生变化

这意味着该文件之后的每个文件都必须在文件中向上推送,从而更改整体存档大小。

您可以通过不压缩该特定文件来解决此问题- CRC 会改变,但整体文件大小不会(只要您保持在该单个文件的边界内。

但是,您至少需要:

  1. 更新文件 CRC
  2. 更新中心目录的 CRC

值得注意的是,位于文件末尾的中央目录是一种巧妙的功能 - 因为这意味着您可以即时生成“动态”zip 文件。我不久前为一家在线销售 MP3 的公司做过这个,我制作了一个“动态”zip 打包器,它基本上将 MP3 文件与正确的 ZIP 标头连接在一起,以便您可以将一堆歌曲添加到“下载列表”中,这会将 MP3 从磁盘上的家中直接流式传输到客户端 - 注入正确的标题信息,最后注入中央目录记录 - 从 Web 服务器端它只是一系列读取和写入,但在客户端上它看起来像一个“真正的”zip 文件。