查看源码 zip (stdlib v6.2)
用于读取和创建 'zip' 归档文件的实用工具。
此模块将文件归档和提取到 zip 归档文件。zip 格式由 “ZIP Appnote.txt” 文件指定,该文件可在 PKWARE 网站 www.pkware.com 上找到。
zip 模块支持最高 6.1 版本的 zip 归档文件。但是,不支持密码保护。
按照惯例,zip 文件的名称应以 .zip
结尾。要遵守惯例,请将 .zip
添加到文件名。
- 要创建 zip 归档文件,请使用函数
zip/2
或zip/3
。它们也可以作为create/2,3
使用,以类似于erl_tar
模块。 - 要从 zip 归档文件中提取文件,请使用函数
unzip/1
或unzip/2
。它们也可以作为extract/1,2
使用,以类似于erl_tar
模块。 - 要对 zip 归档文件中的所有文件折叠一个函数,请使用函数
foldl/3
。 - 要返回 zip 归档文件中文件列表,请使用函数
list_dir/1
或list_dir/2
。它们也可以作为table/1,2
使用,以类似于erl_tar
模块。 - 要在 Erlang shell 中打印文件列表,请使用函数
t/1
或tt/1
。 - 有时,需要打开一个 zip 归档文件,并从中逐个文件解压缩文件,而无需重新打开归档文件。这可以通过函数
zip_open/1,2
、zip_get/1,2
、zip_list_dir/1
和zip_close/1
来完成。 - 支持 ZIP 扩展 0x5355 “扩展时间戳” 和 0x7875 “UID+GID 处理”。默认情况下,在创建归档文件时启用这两个扩展,但在提取时仅启用“扩展时间戳”。使用
extra/0
选项来更改这些扩展的使用方式。
限制
- 不支持受密码保护和加密的归档文件。
- 仅支持 DEFLATE(zlib 压缩)和 STORE(未压缩数据)zip 方法。
- 创建 zip 归档文件时,不支持单个文件的注释。支持整个 zip 归档文件的 zip 归档注释。
- 不支持更改 zip 归档文件。要从归档文件中添加或删除文件,必须重新创建整个归档文件。
摘要
类型
这些选项在 create/3
中描述。
文件扩展名,例如 “.txt”。
可以使用的可能的额外扩展。
zip 文件的名称。
由 zip_open/2
返回。
记录 zip_comment
仅包含 zip 归档文件的归档注释。
记录 zip_file
包含以下字段
函数
在 Archive
中连续的文件上调用 Fun(FileInArchive, GetInfo, GetBin, AccIn)
,从 AccIn == Acc0
开始。
检索 zip 归档文件 Archive
中的所有文件名。
将 zip 归档文件 Archive
中的所有文件名打印到 Erlang shell。(类似于 tar t
。)
将 zip 归档文件 Archive
中所有文件的文件名和信息打印到 Erlang shell。(类似于 tar tv
。)
从 zip 归档文件中提取所有文件。
创建一个 zip 归档文件,其中包含 FileList
中指定的文件。
关闭先前使用 zip_open/1,2
打开的 zip 归档文件。所有资源都将关闭,并且关闭后不得使用句柄。
从打开的归档文件中提取一个或所有文件。
从打开的归档文件中提取一个 crc32 校验和。
返回打开的 zip 归档文件的文件列表。第一个返回的元素是 zip 归档注释。
打开一个 zip 归档文件,并读取和保存其目录。这意味着以后从归档文件中读取文件比使用 unzip/1,2
一次解压缩一个文件更快。
类型
-type create_option() :: memory | cooked | verbose | {comment, Comment :: string()} | {cwd, CWD :: file:filename()} | {compress, What :: extension_spec()} | {uncompress, What :: extension_spec()} | {extra, extra()}.
这些选项在 create/3
中描述。
-type extension() :: string().
文件扩展名,例如 “.txt”。
-type extra() :: [extended_timestamp | uid_gid].
可以使用的可能的额外扩展。
extended_timestamp
- 启用 0x5455 “扩展时间戳” zip 扩展,该扩展为归档文件中的每个文件的访问和修改时间嵌入 POSIX 时间戳。这使得时间戳采用 UTC 而不是本地时间,并且还将时间分辨率从 2 秒提高到 1 秒。uid_gid
- 启用 0x7875 “UNIX 第 3 代” zip 扩展,该扩展将每个文件的 UID 和 GID 嵌入到归档文件中。
-type filename() :: file:filename().
zip 文件的名称。
-opaque handle()
由 zip_open/2
返回。
-type zip_comment() :: #zip_comment{comment :: string()}.
记录 zip_comment
仅包含 zip 归档文件的归档注释。
-type zip_file() :: #zip_file{name :: string(), info :: file:file_info(), comment :: string(), offset :: non_neg_integer(), comp_size :: non_neg_integer()}.
记录 zip_file
包含以下字段
name
- 文件名info
- 文件信息,如 Kernel 中的file:read_file_info/1
中所示。如果使用calendar:datetime/0
表示,则mtime
、atime
和ctime
预计采用本地时间
,如果使用整数表示,则采用 OS 系统时间。comment
- zip 归档文件中文件的注释offset
- zip 归档文件中的文件偏移量(内部使用)comp_size
- 压缩文件的大小(未压缩文件的大小在info
中找到)
erl_tar 兼容性函数
-spec create(Name, FileList) -> RetValue when Name :: file:name(), FileList :: [FileSpec], FileSpec :: file:name() | {file:name(), binary()} | {file:name(), binary(), file:file_info()}, RetValue :: {ok, FileName :: filename()} | {ok, {FileName :: filename(), binary()}} | {error, Reason :: term()}.
等效于 zip(Name, FileList)
。
-spec create(Name, FileList, Options) -> RetValue when Name :: file:name(), FileList :: [FileSpec], FileSpec :: file:name() | {file:name(), binary()} | {file:name(), binary(), file:file_info()}, Options :: [Option], Option :: create_option(), RetValue :: {ok, FileName :: filename()} | {ok, {FileName :: filename(), binary()}} | {error, Reason :: term()}.
-spec extract(Archive) -> RetValue when Archive :: file:name() | binary(), RetValue :: {ok, FileList} | {ok, FileBinList} | {error, Reason :: term()} | {error, {Name :: file:name(), Reason :: term()}}, FileList :: [file:name()], FileBinList :: [{file:name(), binary()}].
等效于 unzip(Archive)
。
-spec extract(Archive, Options) -> RetValue when Archive :: file:name() | binary(), Options :: [Option], Option :: {file_list, FileList} | keep_old_files | verbose | memory | {file_filter, FileFilter} | {cwd, CWD}, FileList :: [file:name()], FileBinList :: [{file:name(), binary()}], FileFilter :: fun((ZipFile) -> boolean()), CWD :: file:filename(), ZipFile :: zip_file(), RetValue :: {ok, FileList} | {ok, FileBinList} | {error, Reason :: term()} | {error, {Name :: file:name(), Reason :: term()}}.
-spec table(Archive) -> RetValue when Archive :: file:name() | binary(), RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()}, CommentAndFiles :: [zip_comment() | zip_file()].
-spec table(Archive, Options) -> RetValue when Archive :: file:name() | binary(), RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()}, CommentAndFiles :: [zip_comment() | zip_file()], Options :: [Option], Option :: cooked.
函数
-spec foldl(Fun, Acc0, Archive) -> {ok, Acc1} | {error, Reason} when Fun :: fun((FileInArchive, GetInfo, GetBin, AccIn) -> AccOut), FileInArchive :: file:name(), GetInfo :: fun(() -> file:file_info()), GetBin :: fun(() -> binary()), Acc0 :: term(), Acc1 :: term(), AccIn :: term(), AccOut :: term(), Archive :: file:name() | {file:name(), binary()}, Reason :: term().
在 Archive
中连续的文件上调用 Fun(FileInArchive, GetInfo, GetBin, AccIn)
,从 AccIn == Acc0
开始。
FileInArchive
是文件在归档文件中的名称。
GetInfo
是返回文件信息的函数。
GetBin
返回文件内容。
必须在 Fun
中调用 GetInfo
和 GetBin
。如果在 Fun
的上下文之外调用它们,则其行为未定义。
Fun
必须返回一个新的累加器,该累加器传递给下一次调用。foldl/3
返回最终累加器值。如果归档文件为空,则返回 Acc0
。没有必要迭代归档文件中的所有文件。可以通过抛出异常以受控方式提前结束迭代。
示例
> Name = "dummy.zip".
"dummy.zip"
> {ok, {Name, Bin}} = zip:create(Name, [{"foo", <<"FOO">>}, {"bar", <<"BAR">>}], [memory]).
{ok,{"dummy.zip",
<<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0,
0,0,3,0,0,...>>}}
> {ok, FileSpec} = zip:foldl(fun(N, I, B, Acc) -> [{N, B(), I()} | Acc] end, [], {Name, Bin}).
{ok,[{"bar",<<"BAR">>,
{file_info,3,regular,read_write,
{{2010,3,1},{19,2,10}},
{{2010,3,1},{19,2,10}},
{{2010,3,1},{19,2,10}},
54,1,0,0,0,0,0}},
{"foo",<<"FOO">>,
{file_info,3,regular,read_write,
{{2010,3,1},{19,2,10}},
{{2010,3,1},{19,2,10}},
{{2010,3,1},{19,2,10}},
54,1,0,0,0,0,0}}]}
> {ok, {Name, Bin}} = zip:create(Name, lists:reverse(FileSpec), [memory]).
{ok,{"dummy.zip",
<<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0,
0,0,3,0,0,...>>}}
> catch zip:foldl(fun("foo", _, B, _) -> throw(B()); (_,_,_,Acc) -> Acc end, [], {Name, Bin}).
<<"FOO">>
-spec list_dir(Archive) -> RetValue when Archive :: file:name() | binary(), RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()}, CommentAndFiles :: [zip_comment() | zip_file()].
-spec list_dir(Archive, Options) -> RetValue when Archive :: file:name() | binary(), RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()}, CommentAndFiles :: [zip_comment() | zip_file()], Options :: [Option], Option :: cooked | {extra, extra()}.
检索 zip 归档文件 Archive
中的所有文件名。
结果值是元组 {ok, List}
,其中 List
将 zip 归档注释作为第一个元素。
一个选项可用
cooked
- 默认情况下,此函数以raw
模式打开 zip 文件,这更快,但不允许使用远程(Erlang)文件服务器。将cooked
添加到模式列表会覆盖默认值,并打开 zip 文件而不使用选项raw
。skip_directories
- 默认情况下,zip 存档中的空目录会被列出。如果设置了选项skip_directories
,则不再列出空目录。{extra, Extras}
- 要考虑的 zip “额外” 功能。支持的“额外”功能是“扩展时间戳”和“UID 和 GID”处理。默认情况下,列出文件时仅启用“扩展时间戳”。有关更多详细信息,请参阅extra/0
。
将 zip 归档文件 Archive
中的所有文件名打印到 Erlang shell。(类似于 tar t
。)
将 zip 归档文件 Archive
中所有文件的文件名和信息打印到 Erlang shell。(类似于 tar tv
。)
-spec unzip(Archive) -> RetValue when Archive :: file:name() | binary(), RetValue :: {ok, FileList} | {ok, FileBinList} | {error, Reason :: term()} | {error, {Name :: file:name(), Reason :: term()}}, FileList :: [file:name()], FileBinList :: [{file:name(), binary()}].
等效于 unzip(Archive, [])
。
-spec unzip(Archive, Options) -> RetValue when Archive :: file:name() | binary(), Options :: [Option], Option :: {file_list, FileList} | cooked | keep_old_files | verbose | memory | {file_filter, FileFilter} | {cwd, CWD} | {extra, extra()}, FileList :: [file:name()], FileBinList :: [{file:name(), binary()}], FileFilter :: fun((ZipFile) -> boolean()), CWD :: file:filename(), ZipFile :: zip_file(), RetValue :: {ok, FileList} | {ok, FileBinList} | {error, Reason :: term()} | {error, {Name :: file:name(), Reason :: term()}}.
从 zip 归档文件中提取所有文件。
如果参数 Archive
被指定为 binary/0
,则假定该二进制文件的内容是一个 zip 存档,否则为文件名。
选项
{file_list, FileList}
- 默认情况下,所有文件都会从 zip 存档中提取。使用选项{file_list, FileList}
,函数unzip/2
仅提取名称包含在FileList
中的文件。必须指定完整路径,包括 zip 存档中所有子目录的名称。cooked
- 默认情况下,此函数以raw
模式打开 zip 文件,这种模式速度更快,但不允许使用远程(Erlang)文件服务器。将cooked
添加到模式列表中会覆盖默认设置,并在不使用raw
选项的情况下打开 zip 文件。提取的文件也适用相同规则。keep_old_files
- 默认情况下,所有与 zip 存档中文件同名的文件都会被覆盖。如果设置了选项keep_old_files
,函数unzip/2
不会覆盖现有文件。请注意,即使指定了memory
选项(这意味着不覆盖任何文件),现有文件也会从结果中排除。skip_directories
- 默认情况下,会提取 zip 存档中的空目录。如果设置了选项skip_directories
,则不再创建空目录。{extra, Extras}
- 要考虑的 zip “额外” 功能。支持的“额外”功能是“扩展时间戳”和“UID 和 GID”处理。默认情况下,解压缩时仅启用“扩展时间戳”。有关更多详细信息,请参阅extra/0
。verbose
- 为每个提取的文件打印信息性消息。memory
- 结果不是提取到当前目录,而是以元组列表{Filename, Binary}
的形式给出,其中Binary
是一个二进制文件,包含 zip 存档中文件Filename
的提取数据。{cwd, CWD}
- 使用指定的目录作为当前目录。当从 zip 存档中提取文件名时,会将其添加到文件名的前面。(类似于 Kernel 中的file:set_cwd/1
,但不会更改全局cwd
属性。)
-spec zip(Name, FileList, Options) -> RetValue when Name :: file:name(), FileList :: [FileSpec], FileSpec :: file:name() | {file:name(), binary()} | {file:name(), binary(), file:file_info()}, Options :: [Option], Option :: create_option(), RetValue :: {ok, FileName :: file:name()} | {ok, {FileName :: file:name(), binary()}} | {error, Reason :: term()}.
创建一个 zip 归档文件,其中包含 FileList
中指定的文件。
FileList
是一个文件列表,其中路径相对于当前目录,并使用此路径存储在存档中。执行文件系统操作以读取文件元数据,并且在启用压缩时,可以流式传输文件内容,而无需将整个文件加载到内存中。也可以将文件指定为二进制文件,以直接从数据创建存档。在这种情况下,不会执行元数据或文件系统读取操作。
文件使用 DEFLATE 压缩进行压缩,如“Appnote.txt”文件中所述。但是,如果文件已经被压缩,则将不进行压缩而存储。 zip/2
和 zip/3
会检查文件扩展名,以确定是否应将文件存储而不进行压缩。具有以下扩展名的文件不会被压缩:.Z
、.zip
、.zoo
、.arc
、.lzh
、.arj
。
可以通过使用选项 {compress, What}
和 {uncompress, What}
来覆盖默认行为,并控制要压缩的文件类型。还可以使用多个 compress
和 uncompress
选项。
要触发文件压缩,其扩展名必须与 compress
条件匹配,且不得与 uncompress
条件匹配。例如,如果将 compress
设置为 ["gif", "jpg"]
,而将 uncompress
设置为 ["jpg"]
,则仅压缩扩展名为 "gif"
的文件。
选项
cooked
- 默认情况下,此函数以raw
模式打开 zip 文件,这种模式速度更快,但不允许使用远程(Erlang)文件服务器。将cooked
添加到模式列表中会覆盖默认设置,并在不使用raw
选项的情况下打开 zip 文件。添加的文件也适用相同规则。verbose
- 打印有关每个添加文件的信息性消息。memory
- 输出不是到一个文件,而是作为一个元组{FileName, binary()}
。该二进制文件是一个完整的 zip 存档,带有标头,可以使用例如unzip/2
进行提取。{comment, Comment}
- 向 zip 存档添加注释。{cwd, CWD}
- 使用指定的目录作为当前工作目录 (cwd
)。这会添加到添加的文件名的前面,但不会添加到 zip 存档中(类似于 Kernel 中的file:set_cwd/1
,但不会更改全局cwd
属性。)。{extra, Extras}
- 要考虑的 zip “额外” 功能。支持的“额外”功能是“扩展时间戳”和“UID 和 GID”处理。默认情况下,这两个“额外”功能都已启用。有关更多详细信息,请参阅extra/0
。{compress, What}
- 控制要压缩的文件类型。默认为all
。允许使用以下What
值all
- 所有文件都被压缩(只要它们通过uncompress
条件)。[Extension]
- 仅压缩具有这些扩展名的文件。{add,[Extension]}
- 将这些扩展名添加到压缩扩展名列表中。{del,[Extension]}
- 从压缩扩展名列表中删除这些扩展名。
{uncompress, What}
- 控制要解压缩的文件类型。默认为[".Z", ".zip", ".zoo", ".arc", ".lzh", ".arj"]
。允许使用以下What
值all
- 不压缩任何文件。[Extension]
- 解压缩具有这些扩展名的文件。{add,[Extension]}
- 将这些扩展名添加到解压缩扩展名列表中。{del,[Extension]}
- 从解压缩扩展名列表中删除这些扩展名。
-spec zip_close(ZipHandle) -> ok | {error, einval} when ZipHandle :: handle().
关闭先前使用 zip_open/1,2
打开的 zip 归档文件。所有资源都将关闭,并且关闭后不得使用句柄。
-spec zip_get(ZipHandle) -> {ok, [Result]} | {error, Reason} when ZipHandle :: handle(), Result :: file:name() | {file:name(), binary()}, Reason :: term().
等效于 zip_get/2
。
-spec zip_get(FileName, ZipHandle) -> {ok, Result} | {error, Reason} when FileName :: file:name(), ZipHandle :: handle(), Result :: file:name() | {file:name(), binary()}, Reason :: term().
从打开的归档文件中提取一个或所有文件。
文件将被解压缩到内存或文件,具体取决于打开存档时为函数 zip_open/1,2
指定的选项。
-spec zip_get_crc32(FileName, ZipHandle) -> {ok, CRC} | {error, Reason} when FileName :: file:name(), ZipHandle :: handle(), CRC :: non_neg_integer(), Reason :: term().
从打开的归档文件中提取一个 crc32 校验和。
-spec zip_list_dir(ZipHandle) -> {ok, Result} | {error, Reason} when Result :: [zip_comment() | zip_file()], ZipHandle :: handle(), Reason :: term().
返回打开的 zip 归档文件的文件列表。第一个返回的元素是 zip 归档注释。
-spec zip_open(Archive) -> {ok, ZipHandle} | {error, Reason} when Archive :: file:name() | binary(), ZipHandle :: handle(), Reason :: term().
等效于 zip_open/2
。
-spec zip_open(Archive, Options) -> {ok, ZipHandle} | {error, Reason} when Archive :: file:name() | binary(), ZipHandle :: handle(), Options :: [Option], Option :: cooked | memory | {cwd, CWD :: file:filename()} | {extra, extra()}, Reason :: term().
打开一个 zip 归档文件,并读取和保存其目录。这意味着以后从归档文件中读取文件比使用 unzip/1,2
一次解压缩一个文件更快。
这些选项与 unzip/2
中的选项等效。
存档必须使用 zip_close/1
关闭。
如果最初打开存档的进程死亡,则 ZipHandle
会被关闭。