我有很多带有文本文件的 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 文件?
如果不做一些可能不受 zipfile 模块开箱即用的低级猴子业务,您就无法做到这一点。然而,这是可能的。
首先快速解释一下 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 会改变,但整体文件大小不会(只要您保持在该单个文件的边界内。
但是,您至少需要:
值得注意的是,位于文件末尾的中央目录是一种巧妙的功能 - 因为这意味着您可以即时生成“动态”zip 文件。我不久前为一家在线销售 MP3 的公司做过这个,我制作了一个“动态”zip 打包器,它基本上将 MP3 文件与正确的 ZIP 标头连接在一起,以便您可以将一堆歌曲添加到“下载列表”中,这会将 MP3 从磁盘上的家中直接流式传输到客户端 - 注入正确的标题信息,最后注入中央目录记录 - 从 Web 服务器端它只是一系列读取和写入,但在客户端上它看起来像一个“真正的”zip 文件。