大文件要用 File.stream!
来分段读取, 否则一下子读到内存里会撑爆内存.
erlang 的 :crypto
标准库中有内置 :crypto.hash_init/1
:crypto.hash_update/2
和 :crypto.hash_final/1
这三个函数, 帮助我们进行分步的哈希运算.
所以最后可以写成:
def sha256_file(path) when is_binary(path) do
File.stream!(path, [], 2048)
|> Enum.reduce(:crypto.hash_init(:sha256), &:crypto.hash_update(&2, &1))
|> :crypto.hash_final()
|> Base.encode16(case: :lower)
end
验证一下:
$ openssl dgst -sha256 SwiftForth-linux-macos-eval.tgz
SHA256(SwiftForth-linux-macos-eval.tgz)= b9870ccafc0713ae80ff2ee3645592622012b6155a8a2e6a396ceb89b7845d98
iex()> BexLib.Crypto.sha256_file "/Downloads/SwiftForth-linux-macos-eval.tgz"
"b9870ccafc0713ae80ff2ee3645592622012b6155a8a2e6a396ceb89b7845d98"