I need to calculate the md5 sum of a file in Elixir, how can this be achieved? 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.
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 . . .
Check out this blog posting: 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 file
a12eb062eca9d1e6c69fcf8b603787c3 file
I have used the information Ryan provided in the comments above, and added the Base.encode16 to reach the final result.
I don't know elixir, but in erlang proper, crypto:hash/2
takes iodata, which a file handle is not. You need to read the file and pass the content to hash(). If you know the file is fairly small, {ok, Content} = file:read_file("file")
(or the elixir equivalent) would do the trick.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With