erlang - 在 Elixir 中声明 zip 存档内容的最佳方法是什么?

标签 erlang elixir zip

目前我在做什么:

  • 通过压缩文件/目录来测试功能。断言它存在。
  • 使用 :zip.t:zip.tt让它列出 zip 文件夹的内容,看看它是否是我所期望的。

  • 不知何故,我觉得我错过了一些东西。用 :zip.table 测试更好吗? ?该功能看起来令人困惑。有人可以提供一个如何使用它的例子吗?下面是我得到的输出示例,但我不知道如何将其变成测试? md5sum 是对 zip 文件更好的测试吗?
    iex(4)> :zip.table('testing.zip')
    {:ok,
     [{:zip_comment, []},
      {:zip_file, 'mix.exs',
       {:file_info, 930, :regular, :read_write, {{2015, 7, 15}, {2, 11, 9}},
        {{2015, 7, 15}, {2, 11, 9}}, {{2015, 7, 15}, {2, 11, 9}}, 54, 1, 0, 0, 0, 0,
        0}, [], 0, 444},
      {:zip_file, 'mix.lock',
       {:file_info, 332, :regular, :read_write, {{2015, 7, 15}, {2, 9, 6}},
        {{2015, 7, 15}, {2, 9, 6}}, {{2015, 7, 15}, {2, 9, 6}}, 54, 1, 0, 0, 0, 0,
        0}, [], 481, 152}]}
    

    最佳答案

    :zip Erlang 的模块并不容易使用,我会尝试为您分解它。

    首先,我们需要zip_file 的适当表示。记录以便从 Erlang 能够正确使用它。否则,我们将不得不对包含大量元素的元组进行匹配,这只会不必要地使我们的代码困惑。以下模块大量基于 the File.Stat implementation from Elixir并将允许我们使用简单的点符号访问那些笨重的元组中的值。

    require Record
    
    defmodule Zip.File do
      record = Record.extract(:zip_file, from_lib: "stdlib/include/zip.hrl")
      keys   = :lists.map(&elem(&1, 0), record)
      vals   = :lists.map(&{&1, [], nil}, keys)
      pairs  = :lists.zip(keys, vals)
    
      defstruct keys
    
      def to_record(%Zip.File{unquote_splicing(pairs)}) do
        {:zip_file, unquote_splicing(vals)}
      end
    
      def from_record(zip_file)
      def from_record({:zip_file, unquote_splicing(vals)}) do
        %Zip.File{unquote_splicing(pairs)}
        |> Map.update!(:info, fn(info) -> File.Stat.from_record(info) end)
      end
    end
    

    我们现在可以围绕 Erlang zip 构建一个小型包装类。模块。它不包含所有方法,仅包含我们将在此处使用的方法。我还添加了 list_files/1仅返回文件的函数,不包括列表中的目录和注释。
    defmodule Zip do
      def open(archive) do
        {:ok, zip_handle} = :zip.zip_open(archive)
        zip_handle
      end
    
      def close(zip_handle) do
        :zip.zip_close(zip_handle)
      end
    
      def list_dir(zip_handle) do
        {:ok, result} = :zip.zip_list_dir(zip_handle)
        result
      end
    
      def list_files(zip_handle) do
        list_dir(zip_handle)
        |> Enum.drop(1)
        |> Enum.map(&Zip.File.from_record/1)
        |> Enum.filter(&(&1.info.type == :regular))
      end
    end
    

    假设我们有以下用于测试的 zip 存档:
    cd /tmp
    touch foo bar baz
    zip archive.zip foo bar baz
    

    现在您可以在 zip 存档中声明文件名:
    test "files are in zip" do
      zip = Zip.open('/tmp/archive.zip')
      files = Zip.list_files(zip) |> Enum.map(&(&1.name))
      Zip.close(zip)
      assert files == ['foo', 'bar', 'baz']
    end
    

    我将在 zip 存档上留下进一步的操作和断言供您实现,并希望这可以帮助您入门。

    关于erlang - 在 Elixir 中声明 zip 存档内容的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31414428/

    相关文章:

    erlang - 如何有效地存储一大组排列?

    c - 如何使用 minizip 库提取符号链接(symbolic link)

    java - Java 中包含文件和子目录的 zip 目录,没有绝对路径

    php - zip_open();在 PHP 5.2.8 上未定义

    Erlang 在生产中启动应用程序

    erlang - 如何在使用 relx 发布汇编程序构建的应用程序中正确使用同步?

    java - 在ejabberd中安装mod_xmlrpc后出错

    elixir - 在 Phoenix Framework 中为整数添加分隔符

    error-handling - 为什么 Elixir 中有两种指示错误的方式?

    elixir - 在 Ecto 中同时创建具有所需foreign_id的父子嵌套关联