我知道如何在Elixir中以写入模式打开一个zip文件:
file = File.open("myzip.zip", [:write, :compressed])
但在此之后,如果我有一个目录/home/lowks/big_files
,我该如何将其写入file
?
答案 0 :(得分:9)
如果您使用的是zip文件,则需要使用:zip.extract('foo.zip')
和:zip.create(name, [{'foo', file1data}, file2path, ...])
。
:zip.create
采用名称和列表,其中包含两个选项之一:
:zip.extract
可以获取文件的路径,也可以使用代表zip存档的二进制数据(可能来自zip上的File.open
)。
您可以执行以下操作来获取路径中的文件列表并将其压缩:
files = File.ls!(path)
|> Enum.map(fn filename -> Path.join(path, filename) end)
|> Enum.map(&String.to_char_list!/1)
:zip.create('foo.zip', files)
答案 1 :(得分:0)
这是一个相当不错的答案,但这里有一个更好的答案,它支持从一个位置递归地向zip添加目录。
files = create_files_list(path)
:zip.create(to_charlist(zip_file_path), files)
这是create_files_list:
defp create_files_list(path) do
create_files_list(File.ls!(path), path)
end
defp create_files_list(paths, path) do
create_files_list(paths, path, path)
end
defp create_files_list(paths, path, base_path) do
Enum.reduce(paths, [],
fn(filename, acc) ->
filename_path = Path.join(path, filename)
if File.dir?(filename_path) do
acc ++ create_files_list(File.ls!(filename_path), filename_path, base_path)
else
filenm =
if base_path,
do: String.replace_leading(filename_path, base_path, ""),
else: filename_path
[{String.to_char_list(filenm), File.read!(filename_path)} | acc]
end
end
)
end
一句警告;我没有将它用于任何非常大的东西,它可能会在这里使用File.read来破坏一切。我不确定如何使用文件句柄,但我认为这是可能的。随意改进和贡献; - )
我也会缓存zip文件,因此每次都不会执行。