Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/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
File 检查两个文件是否相等的最快哈希算法是什么?_File_Hash_Crc - Fatal编程技术网

File 检查两个文件是否相等的最快哈希算法是什么?

File 检查两个文件是否相等的最快哈希算法是什么?,file,hash,crc,File,Hash,Crc,创建用于检查两个文件是否相等的哈希函数的最快方法是什么 安全不是很重要 编辑:我正在通过网络连接发送一个文件,并将确保两侧的文件相等一种方法可能是使用简单的CRC-32算法,并且只有当CRC值比较相等时,才使用SHA1或更健壮的方法重新运行哈希。快速CRC-32在任何一天都会优于加密安全哈希。为什么要对其进行哈希 如果您想确保两个文件相等,那么根据定义,您必须读取整个文件(除非它们实际上是同一个文件,在这种情况下,您可以通过查看文件系统上的元数据来判断)。不管怎样,没有理由散列,只要把它们读一遍

创建用于检查两个文件是否相等的哈希函数的最快方法是什么

安全不是很重要


编辑:我正在通过网络连接发送一个文件,并将确保两侧的文件相等

一种方法可能是使用简单的CRC-32算法,并且只有当CRC值比较相等时,才使用SHA1或更健壮的方法重新运行哈希。快速CRC-32在任何一天都会优于加密安全哈希。

为什么要对其进行哈希

如果您想确保两个文件相等,那么根据定义,您必须读取整个文件(除非它们实际上是同一个文件,在这种情况下,您可以通过查看文件系统上的元数据来判断)。不管怎样,没有理由散列,只要把它们读一遍,看看它们是否相同。散列会降低效率。即使散列匹配,您仍然无法确定这些文件是否真的相等


编辑:此答案在问题指定任何有关网络的内容之前发布。它只是询问比较两个文件。既然我知道两个文件之间有一个网络跳转,我想说只要使用MD5散列就可以了。

如果只是一次性的,那么考虑到您必须读取两个文件才能生成两个文件的散列,为什么不一次读取一小部分并进行比较呢


失败的是一个非常简单的算法。

您可以尝试,它是专门为快速而设计的,并且代码非常简单。如果BurruHash返回一个匹配项,您可能需要使用第二个更安全的哈希,这只是为了确保。

对于这种类型的应用程序,可能是最快的算法,具有合理的安全级别。对于较大的文件,您可以计算多个散列值,例如每5 Mb文件块计算一个散列值,从而减少出错的机会(即散列相同但文件内容不同的情况)。此外,该多散列值设置可允许以多线程方式实现散列的计算

编辑:(在史蒂文·苏迪特的评论之后)
如果文件太小,请注意
Adler32的“加密”特性,或者更确切地说,它的弱点是众所周知的,特别是对于短消息。因此,对于小于几千字节的文件,应避免使用建议的解决方案。

然而,在这个问题上,OP明确地寻求一种快速算法,并放弃了对安全性的担忧。此外,对速度的追求似乎意味着一个人正在处理“大”文件而不是小文件。在这种情况下,Adler32(可能并行应用于文件块,比如5Mb)仍然是一个非常有效的答案。Alder32以其简单和快速而闻名。此外,它的可靠性虽然低于相同长度的CRC,但对于超过4000字节的消息来说是可以接受的。

除非您使用的是非常复杂和/或缓慢的哈希,否则从磁盘加载数据所需的时间将比计算哈希要长得多(除非您使用RAM磁盘或高端SSD)

因此,要比较两个文件,请使用以下算法:

  • 比较大小
  • 比较日期(这里要小心:这可能会给你错误的答案;你必须测试这是否适合你)
  • 比较散列
这允许快速失败(如果大小不同,您知道文件不同)


为了让事情变得更快,您可以计算一次散列并将其与文件一起保存。还可以将文件日期和大小保存到这个额外的文件中,以便在主文件更改时快速知道何时必须重新计算哈希或删除哈希文件。

您可以查看samba/rsync开发人员使用的算法。我没有深入研究它,但我看到它一直被提及。显然,它很好。

xxhash声称自己速度很快,强度很强,在碰撞方面:


总的来说,有一种64位变体在64位处理器上的运行速度比32位处理器“更快”,尽管在32位处理器上运行速度较慢(见图)

也可以说是相当快的(并且在存在硬件CRC指令的地方利用硬件CRC指令,这些指令可能非常快,但是如果您没有支持它们的硬件,它们就没有那么快)。不知道CRC32c是否和xxHash一样好(就冲突而言)

似乎与crcutil类似并相关[因为如果有指示,它可以向下编译以使用硬件CRC32c指令]


如果您“只想要最快的原始速度”,而不太关心散列输出的随机分布的质量(例如,对于小集合,或者速度是最重要的),这里提到了一些快速算法:(在某些情况下,这些“不太随机”分布类型的算法“足够好”并且非常快)。显然,
FNV1A_jesteres
对于“长”字符串是最快的,而对于小字符串可能是最快的。似乎也有关联。我没有研究这些文件的冲突属性。

在任何情况下,您都应该完全读取每个文件(大小不匹配的情况除外),所以只需读取两个文件并逐块比较


使用散列只会增加CPU使用率,仅此而已。由于您不写任何东西,操作系统的缓存将有效地删除您读取的数据,因此,在Linux下,只需使用

以下代码从我的个人项目中查找重复文件,以对图片进行排序,同时删除重复的图片。根据我的经验,首先使用像CRC32这样的快速哈希算法,然后执行MD5或SHA1更慢,并且没有任何改进,因为大多数大小相同的文件确实是重复的,所以从cpu时间的角度来看,运行两次哈希更昂贵,这种方法可能并不适用于所有类型的项目,但对于图像文件来说确实如此。在这里,我正在做MD5或S
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;

    import org.apache.commons.codec.digest.DigestUtils;

    /**
     * Finds the duplicate files using md5/sha1 hashing, which is used only for the sizes which are of same size.
     *  
     * @author HemantSingh
     *
     */
    public class DuplicateFileFinder {

        private HashProvider hashProvider;
        // Used only for logging purpose.
        private String hashingAlgo;

        public DuplicateFileFinder(String hashingAlgo) {
            this.hashingAlgo = hashingAlgo;
            if ("SHA1".equalsIgnoreCase(hashingAlgo)) {
                hashProvider = new Sha1HashProvider();
            } else if ("MD5".equalsIgnoreCase(hashingAlgo)) {
                hashProvider = new Md5HashProvider();
            } else {
                throw new RuntimeException("Unsupported hashing algorithm:" + hashingAlgo + " Please use either SHA1 or MD5.");
            }
        }

        /**
         * This API returns the list of duplicate files reference.
         * 
         * @param files
         *            - List of all the files which we need to check for duplicates.
         * @return It returns the list which contains list of duplicate files for
         *         e.g. if a file a.JPG have 3 copies then first element in the list
         *         will be list with three references of File reference.
         */
        public List<List<File>> findDuplicateFilesList(List<File> files) {
            // First create the map for the file size and file reference in the array list.
            Map<Long, List<File>> fileSizeMap = new HashMap<Long, List<File>>();
            List<Long> potDuplicateFilesSize = new ArrayList<Long>();

            for (Iterator<File> iterator = files.iterator(); iterator.hasNext();) {
                File file = (File) iterator.next();
                Long fileLength = new Long(file.length());
                List<File> filesOfSameLength = fileSizeMap.get(fileLength);
                if (filesOfSameLength == null) {
                    filesOfSameLength = new ArrayList<File>();
                    fileSizeMap.put(fileLength, filesOfSameLength);
                } else {
                    potDuplicateFilesSize.add(fileLength);
                }
                filesOfSameLength.add(file);
            }

            // If we don't have any potential duplicates then skip further processing.
            if (potDuplicateFilesSize.size() == 0) {
                return null;
            }

            System.out.println(potDuplicateFilesSize.size() + " files will go thru " + hashingAlgo + " hash check to verify if they are duplicate.");

            // Now we will scan the potential duplicate files, and eliminate false positives using md5 hash check.
            List<List<File>> finalListOfDuplicates = new ArrayList<List<File>>();
            for (Iterator<Long> potDuplicatesFileSizeIterator = potDuplicateFilesSize
                    .iterator(); potDuplicatesFileSizeIterator.hasNext();) {
                Long fileSize = (Long) potDuplicatesFileSizeIterator.next();
                List<File> potDupFiles = fileSizeMap.get(fileSize);
                Map<String, List<File>> trueDuplicateFiles = new HashMap<String, List<File>>();
                for (Iterator<File> potDuplicateFilesIterator = potDupFiles.iterator(); potDuplicateFilesIterator
                        .hasNext();) {
                    File file = (File) potDuplicateFilesIterator.next();
                    try {
                        String md5Hex = hashProvider.getHashHex(file);
                        List<File> listOfDuplicatesOfAFile = trueDuplicateFiles.get(md5Hex);
                        if (listOfDuplicatesOfAFile == null) {
                            listOfDuplicatesOfAFile = new ArrayList<File>();
                            trueDuplicateFiles.put(md5Hex, listOfDuplicatesOfAFile);
                        }
                        listOfDuplicatesOfAFile.add(file);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                Collection<List<File>> dupsOfSameSizeList = trueDuplicateFiles.values();
                for (Iterator<List<File>> dupsOfSameSizeListIterator = dupsOfSameSizeList.iterator(); dupsOfSameSizeListIterator
                        .hasNext();) {
                    List<File> list = (List<File>) dupsOfSameSizeListIterator.next();
                    // It will be duplicate only if we have more then one copy of it.
                    if (list.size() > 1) {
                        finalListOfDuplicates.add(list);
                        System.out.println("Duplicate sets found: " + finalListOfDuplicates.size());
                    }
                }
            }

            return finalListOfDuplicates;
        }

        abstract class HashProvider {
            abstract String getHashHex(File file) throws IOException ;
        }

        class Md5HashProvider extends HashProvider {
            String getHashHex(File file) throws IOException {
                return DigestUtils.md5Hex(new FileInputStream(file));
            }
        }
        class Sha1HashProvider extends HashProvider {
            String getHashHex(File file) throws IOException {
                return DigestUtils.sha1Hex(new FileInputStream(file));
            }
        }
    }