Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hash 在F中使用MD5#_Hash_F#_Md5 - Fatal编程技术网

Hash 在F中使用MD5#

Hash 在F中使用MD5#,hash,f#,md5,Hash,F#,Md5,我目前正在努力学习F#。这是我第一次使用.NET语言,因此我对可用的API非常不熟悉 作为一个初学者的项目,我想实现我自己的重复文件查找器。有人建议我使用校验和,因为我比较的文件很大(大多在1MB到10MB之间) 到目前为止,我所做的就是:检查文件长度后,通过将所有字节读入字节数组,比较具有相同文件长度的文件。现在我想使用MD5计算每个字节数组的哈希值,然后删除共享相同哈希值的重复文件 我有一些问题: 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";;