Elixir用pin操作符匹配位串报错及无元编程动态匹配方案咨询
MatchError报错原因
这个错误的根本原因是Elixir二进制模式匹配的默认段规则:未指定类型的段默认是integer类型、默认长度为8bit(1字节)。你写的<<^bmp_signature, _::binary>>会被解析为「匹配第一个字节的整数值等于bmp_signature的值,后面跟着任意二进制」,但bmp_signature是2字节的二进制值,和第一个字节的66完全不相等,因此匹配失败抛出MatchError。
如果你想要匹配和bmp_signature等长的前缀,需要显式指定该段的类型为binary,且长度等于bmp_signature的字节数,正确写法如下:
<<^bmp_signature::binary-size(byte_size(bmp_signature)), _::binary>> = <<66, 77, 30, 0>>
这样就可以正常匹配成功。
动态匹配文件类型的实现方案
你的需求完全可以不用元编程实现,只需要修改detect_type函数中的匹配逻辑,每次匹配时显式指定签名的长度即可,修改后的可运行代码如下:
@signatures %{ "bmp" => <<66, 77>>, # 其他格式签名可直接在该映射中补充 } def detect_type(file) do find_value_func = fn {extension, signature} -> sig_len = byte_size(signature) case file do <<^signature::binary-size(sig_len), _::binary>> -> extension _ -> false end end Enum.find_value(@signatures, find_value_func) end
该方案完全在运行期遍历匹配,不需要生成任何动态函数,符合你的需求。
内容的提问来源于stack exchange,提问作者kinkou
相关产品推荐
相关产品推荐

