在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码:

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

在这种情况下,我只需要QR数据,即Hello world ,但它返回一个元组,第一个值是字符串,第二个是0。我很想知道为什么返回0。
我试着扫描一个无效的QR码图像,如Codemancers的标志:


注意,现在它返回4。对于无效的或非QR码的图像,zbarimg 库将返回4。
那无效的文件类型呢?

我们可以为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码数据:

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

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

现有的代码可以被更新到:
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码数据。以下是从二维码图像中提取的数据的截图:

更新:我从Antonin Kral那里收到了关于解析QR码数据的建议,内容如下。
如果存储在二维码中的数据由多行组成,建议在使用--xml 选项。zbarimg

Elixir代码将是:
args = ["--xml", image_path]
System.cmd("zbarimg", args, stderr_to_stdout: true)
注意:在我们客户的要求中,二维码数据没有跨越多行,因此我在例子中没有使用--xml 选项。