在Elixir中从QR码中提取数据的指南

119 阅读2分钟

在Elixir中从QR码中提取数据

在我为我们的一个客户完成了使用Elixir编写QR码生成器的工作后,有一个要求,即从QR码中提取数据并存储。这篇文章是关于我如何学会在Elixir中提取QR码的数据。

我在寻找一个读取二维码的工具时遇到了zbar。由于我将使用这个工具来读取二维码图像,我将不得不在我的代码中使用System.cmd() ,以运行zbar二进制。

	defmodule Sample do
	  def qr_string(image_path) do
	    System.cmd("zbarimg", [image_path], stderr_to_stdout: true)
	  end
	end

stderr_to_stdout 选项被设置为 "true "时,错误细节将包括在由Sysmtem.cmd 返回的元组中。

我生成了一个以Hello world 为数据的QR码:

screenshot1

当我运行上述代码时,我得到以下结果:

screenshot1

在这种情况下,我只需要QR数据,即Hello world ,但它返回一个元组,第一个值是字符串,第二个是0。我很想知道为什么返回0。

我试着扫描一个无效的QR码图像,如Codemancers的标志:

screenshot1

screenshot1

注意,现在它返回4。对于无效的或非QR码的图像,zbarimg 库将返回4。

那无效的文件类型呢?

screenshot1

我们可以为0提取数据,为4返回 "没有QR码存在",为其他任何东西返回 "无效的文件":

    defmodule Sample
 
      require Logger

      def qr_string(image_path) do
        case System.cmd("zbarimg", [image_path], stderr_to_stdout: true) do
          {data, 0} ->
            data

          {data, 4} ->
            raise Logger.info("No QR code present. msg: #{data}")

          {data, _} ->
            raise Logger.info("Invalid file. msg: #{data}")
        end
      end
    end

我们仍然需要从字符串中提取QR码数据:

screenshot1

我们可以分割字符串并找到数据:

screenshot1

我遇到了<> 操作符,它可以用于字符串模式匹配,使用它我可以在字符串中找到数据:

screenshot1

现有的代码可以被更新到:

    case System.cmd("zbarimg", [image_path], stderr_to_stdout: true) do

      {data, 0} ->
        "QR-Code:" <> result =
          data
          |> String.split("\n")
          |> List.first()

        result

      {data, 4} ->
        raise Logger.info("No QR code present. msg: #{data}")

      {data, _} ->
        raise Logger.info("Invalid file. msg: #{data}")
    end

我能够从QR码图像中提取QR码数据。以下是从二维码图像中提取的数据的截图:

screenshot1

更新:我从Antonin Kral那里收到了关于解析QR码数据的建议,内容如下。

如果存储在二维码中的数据由多行组成,建议在使用--xml 选项。zbarimg

screenshot1

Elixir代码将是:

    args = ["--xml", image_path]
    System.cmd("zbarimg", args, stderr_to_stdout: true)

注意:在我们客户的要求中,二维码数据没有跨越多行,因此我在例子中没有使用--xml 选项。