我想使用多个算法放哈给定文件,但现在我会顺序进行,这样:
return [
hash_file('md5', $uri),
hash_file('sha1', $uri),
hash_file('sha256', $uri)
];
无论如何,该文件是否只打开一个流,而不是我要使用的algos的数量?这样的东西:
return hash_file(['md5', 'sha1', 'sha256'], $uri);
您可以打开文件指针,然后将hash_init((与hash_update((一起使用hash_init((来计算文件上的哈希,而无需打开文件,然后使用hash_final((获取结果哈希。
<?php
function hash_file_multi($algos = [], $filename) {
if (!is_array($algos)) {
throw new InvalidArgumentException('First argument must be an array');
}
if (!is_string($filename)) {
throw new InvalidArgumentException('Second argument must be a string');
}
if (!file_exists($filename)) {
throw new InvalidArgumentException('Second argument, file not found');
}
$result = [];
$fp = fopen($filename, "r");
if ($fp) {
// ini hash contexts
foreach ($algos as $algo) {
$ctx[$algo] = hash_init($algo);
}
// calculate hash
while (!feof($fp)) {
$buffer = fgets($fp, 65536);
foreach ($ctx as $key => $context) {
hash_update($ctx[$key], $buffer);
}
}
// finalise hash and store in return
foreach ($algos as $algo) {
$result[$algo] = hash_final($ctx[$algo]);
}
fclose($fp);
} else {
throw new InvalidArgumentException('Could not open file for reading');
}
return $result;
}
$result = hash_file_multi(['md5', 'sha1', 'sha256'], $uri);
var_dump($result['md5'] === hash_file('md5', $uri)); //true
var_dump($result['sha1'] === hash_file('sha1', $uri)); //true
var_dump($result['sha256'] === hash_file('sha256', $uri)); //true
还发布到PHP手册:http://php.net/manual/en/function.hash-file.php#122549
这是对劳伦斯·切罗隆(Lawrence Cherone(的解决方案*的修改,它仅读取文件一次,甚至适用于诸如STDIN
:
<?php
function hash_stream_multi($algos = [], $stream) {
if (!is_array($algos)) {
throw new InvalidArgumentException('First argument must be an array');
}
if (!is_resource($stream)) {
throw new InvalidArgumentException('Second argument must be a resource');
}
$result = [];
foreach ($algos as $algo) {
$ctx[$algo] = hash_init($algo);
}
while (!feof($stream)) {
$chunk = fread($stream, 1 << 20); // read data in 1 MiB chunks
foreach ($algos as $algo) {
hash_update($ctx[$algo], $chunk);
}
}
foreach ($algos as $algo) {
$result[$algo] = hash_final($ctx[$algo]);
}
return $result;
}
// test: hash standard input with MD5, SHA-1 and SHA-256
$result = hash_stream_multi(['md5', 'sha1', 'sha256'], STDIN);
print_r($result);
在线尝试!
它通过在块中使用fread()
从输入流中读取数据(一个兆字节,应在性能和内存使用之间给出合理的平衡(,并用hash_update()
给出每个哈希的块。
*(劳伦斯在我写这篇文章时更新了他的答案,但我觉得我的仍然足够不同,足以证明保留两个。该解决方案和劳伦斯更新版本之间的主要区别在于,我的函数采用输入流而不是文件名,并且我使用的是fread()
而不是fgets()
(因为对于Hashing,无需在Newlines上拆分输入(。