Hash 在F中使用MD5#
我目前正在努力学习F#。这是我第一次使用.NET语言,因此我对可用的API非常不熟悉 作为一个初学者的项目,我想实现我自己的重复文件查找器。有人建议我使用校验和,因为我比较的文件很大(大多在1MB到10MB之间) 到目前为止,我所做的就是:检查文件长度后,通过将所有字节读入字节数组,比较具有相同文件长度的文件。现在我想使用MD5计算每个字节数组的哈希值,然后删除共享相同哈希值的重复文件 我有一些问题:Hash 在F中使用MD5#,hash,f#,md5,Hash,F#,Md5,我目前正在努力学习F#。这是我第一次使用.NET语言,因此我对可用的API非常不熟悉 作为一个初学者的项目,我想实现我自己的重复文件查找器。有人建议我使用校验和,因为我比较的文件很大(大多在1MB到10MB之间) 到目前为止,我所做的就是:检查文件长度后,通过将所有字节读入字节数组,比较具有相同文件长度的文件。现在我想使用MD5计算每个字节数组的哈希值,然后删除共享相同哈希值的重复文件 我有一些问题: MD5是否适合此任务 如果不是,我应该使用什么算法 谢谢你的帮助。我可能会在您的回复后发布后续
我想提取具有多个值(对应文件)的键(散列字节数组),并删除重复的文件。如何改进和继续上面的代码示例?我不熟悉MD5的工作原理,所以我被困在这里。如果您有任何建议,我们将不胜感激。使用MD5完成此任务没有什么特别的错误。然而,MD5不再被认为是“强”散列;对于确定的各方来说,创建具有不同内容但具有相同MD5哈希的文件相对简单 一个更健壮的替代方案,我建议您使用SHA-2散列,比如SHA256 但是,性能注意事项:如果缓存文件的哈希(并在添加/删除/修改文件时增量更新缓存),则哈希只能提高工具的性能。如果不缓存哈希值,则需要读取两个文件的全部内容,并在每次发现冲突时计算它们的哈希值;如果此工具仅用于临时重复数据消除,则在发现相同大小的文件时,比较文件内容可能会更快/更简单 编辑:下面是一些您可以使用的示例代码。它将检测重复项,但您需要编写另一个函数来确定如何解决冲突(例如,您可能希望保留最早创建的文件)
opensystem.IO
开放系统、安全性、加密
///给定一系列文件名,通过比较文件长度查找重复文件
///以及,如有必要,使用指定的哈希算法计算哈希值。
///返回元组序列;元组中的第一项是散列值和
///第二项是一个序列,包含两个或多个具有
///相同的长度和哈希值。
让findDuplicateFiles(算法:HashAlgorithm)(文件名:seq)=
文件名
|>Seq.groupBy(有趣的文件名->
(FileInfo filename).Length)
|>Seq.collect(有趣的(u,samelengfilename)->
//如果只有一个文件具有此长度,则不会有重复,因此不要返回它。
如果Seq.length sameLengthFilenames=1,则Seq.empty
其他的
//可能重复。通过对文件进行散列并比较散列来解决。
samelengfilename
|>Seq.groupBy(有趣的文件名->
使用(File.OpenRead filename)算法(ComputeHash)
//检查具有相同哈希值的多个文件。
//返回任何此类文件名,以便外部代码可以确定如何处理它们。
|>Seq.filter(有趣的(u,samelengfilename)->
//两个或多个文件具有相同哈希时发生冲突。
Seq.length SameleLength文件名>2)
///给定一系列文件名,通过比较文件长度查找重复文件
///如有必要,使用SHA256算法计算哈希值。
///返回元组序列;元组中的第一项是散列值和
///第二项是一个序列,包含两个或多个具有
///相同的长度和哈希值。
让findDuplicateFilesSHA256个文件名=
//注意:该算法应在此处与“使用”或“使用”绑定,以便进行处置,
//但是F#3.1编译器似乎过早地处理了对象。
findDuplicateFiles(SHA256.Create())文件名
//
让printDuplicateEntry(散列:字节[],文件名:seq)=
stdout.WriteLine“”
stdout.写“散列:”
stdout.WriteLine(System.BitConverter.ToString(哈希).Replace(“-”,”))
对于文件名中的文件名,请执行以下操作:
printfn“%s(长度:%i)”文件名((FileInfo文件名).Length)
//
让FindDuplicateFileIndirectory路径=
Directory.Enumerate文件(路径)
|>查找重复文件SHA256
|>Seq.iter打印副本条目
;;
//用法示例:
findDuplicateFilesInDirectory@“C:\Users\Jack\Desktop”;;
MD5不安全。。。尝试将SHA256
或更好的HMAC SHA512
用于玩具项目,真的吗?md5适用于此应用程序,如果您比较字节数+md5,则安全性不成问题,这对于所有实际目的都应该是可以的。感谢您的回复。你介意为我提供一些伪代码,这样我就可以使用它了吗?我是编程新手,对哈希和缓存等概念非常不熟悉。谢谢。我添加了一些示例代码。它实际上做了我说过不要做的事情(每次都计算哈希值),但我已经对它进行了测试,性能还不错,因此您可能不需要进一步推动它(例如,缓存文件名/哈希值)。
let readAllBytesMD5 (tupleOfFileLengthsAndFiles) =
let md5 = MD5.Create()
tupleOfFileLengthsAndFiles
|> snd
|> Seq.map (fun eachFile -> (File.ReadAllBytes eachFile, eachFile))
|> Seq.groupBy fst
|> Seq.map (fun (byteArray, eachFile) -> (md5.ComputeHash(byteArray), eachFile))
open System.IO
open System.Security.Cryptography
/// Given a sequence of filenames, looks for duplicate files by comparing file lengths
/// and, if necessary, hash values calculated using the specified hash algorithm.
/// Returns a sequence of tuples; the first item in the tuple is a hash value and the
/// second item is a sequence containing the names of two or more files which have
/// the same length and hash value.
let findDuplicateFiles (algorithm : HashAlgorithm) (filenames : seq<string>) =
filenames
|> Seq.groupBy (fun filename ->
(FileInfo filename).Length)
|> Seq.collect (fun (_, sameLengthFilenames) ->
// If there's only one file with this length, there's no duplication so don't return it.
if Seq.length sameLengthFilenames = 1 then Seq.empty
else
// Possible duplication. Resolve by hashing the files and comparing the hashes.
sameLengthFilenames
|> Seq.groupBy (fun filename ->
using (File.OpenRead filename) algorithm.ComputeHash)
// Check for multiple files with the same hash value.
// Return any such filenames so outside code can determine how to handle them.
|> Seq.filter (fun (_, sameLengthFilenames) ->
// Collision when two or more files have the same hash.
Seq.length sameLengthFilenames > 2))
/// Given a sequence of filenames, looks for duplicate files by comparing file lengths
/// and, if necessary, hash values calculated using the SHA256 algorithm.
/// Returns a sequence of tuples; the first item in the tuple is a hash value and the
/// second item is a sequence containing the names of two or more files which have
/// the same length and hash value.
let findDuplicateFilesSHA256 filenames =
// NOTE: The algorithm should be bound with 'use' or 'using' here so it can be disposed,
// but the F# 3.1 compiler appears to dispose the object too early.
findDuplicateFiles (SHA256.Create()) filenames
//
let printDuplicateEntry (hash : byte[], filenames : seq<string>) =
stdout.WriteLine ""
stdout.Write "Hash: "
stdout.WriteLine (System.BitConverter.ToString(hash).Replace("-", ""))
for filename in filenames do
printfn " %s (Length: %i)" filename ((FileInfo filename).Length)
//
let findDuplicateFilesInDirectory path =
Directory.EnumerateFiles (path)
|> findDuplicateFilesSHA256
|> Seq.iter printDuplicateEntry
;;
// Example usage:
findDuplicateFilesInDirectory @"C:\Users\Jack\Desktop";;