简体   繁体   English

如何计算 Elixir 中的文件校验和?

[英]How can I calculate a file checksum in Elixir?

I need to calculate the md5 sum of a file in Elixir, how can this be achieved?我需要计算Elixir中一个文件的md5和,这怎么实现呢? I would expect that something like:我希望是这样的:

iex(15)> {:ok, f} = File.open "file"
{:ok, #PID<0.334.0>}
iex(16)> :crypto.hash(:md5, f)
** (ArgumentError) argument error
             :erlang.iolist_to_binary(#PID<0.334.0>)
    (crypto) crypto.erl:225: :crypto.hash/2

But clearly it doesn't work..但显然它不起作用..

The documentation of Mix.Utils tells about read_path/2 , but it didn't worked either. Mix.Utils 的文档讲述了read_path/2 ,但它也不起作用。

iex(22)> Mix.Utils.read_path("file", [:sha512])  
{:ok, "Elixir"} #the expected was {:checksum, "<checksum_value>"}

Is there any library that provides such functionality in a easy way?是否有任何库以简单的方式提供此类功能?

In case anyone else finds this question and misses @FredtheMagicWonderDog's comment .万一其他人发现这个问题并错过了@FredtheMagicWonderDog 的评论。 . . . .

Check out this blog posting: http://www.cursingthedarkness.com/2015/04/how-to-get-hash-of-file-in-exilir.html查看此博客文章: http : //www.cursingthedarkness.com/2015/04/how-to-get-hash-of-file-in-exilir.html

And here's the relevant code:这是相关的代码:

File.stream!("./known_hosts.txt",[],2048) 
|> Enum.reduce(:crypto.hash_init(:sha256),fn(line, acc) -> :crypto.hash_update(acc,line) end ) 
|> :crypto.hash_final 
|> Base.encode16 


#=> "97368E46417DF00CB833C73457D2BE0509C9A404B255D4C70BBDC792D248B4A2" 

NB: I'm posting this as community wiki.注意:我将此作为社区维基发布。 I'm not trying to get rep points;我不是想获得代表积分; just trying to ensure the answer isn't buried in comments.只是想确保答案不会隐藏在评论中。

This also does the job:这也可以完成工作:

iex(25)> {:ok, content} = File.read "file"
{:ok, "Elixir"}
iex(26)> :crypto.hash(:md5, content) |> Base.encode16   
"A12EB062ECA9D1E6C69FCF8B603787C3"

The md5sum program on the same file returned:同一文件上的 md5sum 程序返回:

$ md5sum file 
a12eb062eca9d1e6c69fcf8b603787c3  file

I have used the information Ryan provided in the comments above, and added the Base.encode16 to reach the final result.我使用了上面评论中 Ryan 提供的信息,并添加了 Base.encode16 以达到最终结果。

I don't know elixir, but in erlang proper, crypto:hash/2 takes iodata, which a file handle is not.我不知道长生不老药,但在 erlang 中, crypto:hash/2采用 iodata,而文件句柄不是。 You need to read the file and pass the content to hash().您需要读取文件并将内容传递给 hash()。 If you know the file is fairly small, {ok, Content} = file:read_file("file") (or the elixir equivalent) would do the trick.如果您知道文件相当小,那么{ok, Content} = file:read_file("file") (或等效的 elixir)可以解决问题。

Besides the @aeliton solution is short and nifty, it has the best performance.除了@aeliton 解决方案短小精悍之外,它还具有最佳性能。

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM