加快MD5检查文件数组

时间:2013-12-25 17:06:17

标签: android performance md5

我正在遍历一个文件数组,以查看其中的任何文件是否与该数组中的最后一个文件匹配:

    List<File> files = Arrays.asList(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).listFiles());
    byte[] md5Downloaded = null;
    try {
        md5Downloaded = createChecksum(files.get(files.size()-1).getAbsolutePath());
    } catch (Exception e1) {
        e1.printStackTrace();
    }

    for(File file : files){

        try {
            byte[] md5CurrentFile = createChecksum(file.getAbsolutePath());


            if(Arrays.equals(md5Downloaded, md5CurrentFile) && counter != files.size()-1 ){
                alertUserMD5(file, files.get(files.size()-1));
                return;
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

这是借用的createChecksum方法:

private static byte[] createChecksum(String filename) throws Exception {
    InputStream fis =  new FileInputStream(filename);

    byte[] buffer = new byte[1024];
    MessageDigest complete = MessageDigest.getInstance("MD5");
    int numRead;

    do {
        numRead = fis.read(buffer);
        if (numRead > 0) {
            complete.update(buffer, 0, numRead);
        }
    } while (numRead != -1);

    fis.close();
    return complete.digest();
}

但是,我不满意这个过程需要的时间(大约15秒)。我意识到我正在做的事情高度依赖于列表中的文件数量,以及这些文件的大小,但有没有办法加快速度呢?

2 个答案:

答案 0 :(得分:1)

private void searchFile() {
    long t = System.currentTimeMillis();
    List<File> files = new ArrayList<File>(Arrays.asList(dir.listFiles()));
    File downloaded = files.get(files.size() - 1);
    files.remove(files.size()-1);
    byte[] md5Downloaded = null;
    try {
        md5Downloaded = createChecksum(downloaded.getAbsolutePath());
    } catch (Exception e1) {
        e1.printStackTrace();
    }

    Collections.sort(files, new Comparator<File>() {
        @Override
        public int compare(File lhs, File rhs) {
            return Long.valueOf(lhs.length()).compareTo(rhs.length());
        }
    });

    final byte[] MD5 = md5Downloaded;

    final int position = Collections.binarySearch(files, downloaded, new Comparator<File>() {
        @Override
        public int compare(File lhs, File rhs) {
            int compare =  Long.valueOf(lhs.length()).compareTo(rhs.length());
            if (compare == 0) {
                try {
                    if (Arrays.equals(MD5, createChecksum(lhs.getAbsolutePath()))) {
                        return 0;
                    }
                } catch (Exception ignored) {

                }
                return -1;
            } else
                return compare;
        }
    });

    if (position >= 0) {
        alertUserMD5(files.get(position), downloaded);
    }

}

对于破碎的例子感到抱歉,在纸上做了#34;&#34;。这是一个有效的例子。在目录中使用578个文件= 154毫秒进行了测试

答案 1 :(得分:0)

看起来您正试图弄清楚某个文件是否已经可用。如果文件往往不相关,则可以仅计算前1024个字节的md5,并与最后一个文件进行比较。如果它不同,则无需比较整个文件的校验和。只有当它们相等时,才需要比较整个文件的md5。

几乎忘了:比较文件大小甚至之前,如果文件大部分都不相关,可能会导致大部分时间提前退出。