如何使用java或groovy计算目录上的md5校验和?

如何使用java或groovy计算目录上的md5校验和?,java,groovy,directory,md5,checksum,Java,Groovy,Directory,Md5,Checksum,我希望使用java或groovy获得完整目录的md5校验和 我必须将源目录复制到目标目录,对源目录和目标目录进行校验,然后删除源目录 我发现这个脚本用于文件,但如何对目录执行相同的操作 import java.security.MessageDigest def generateMD5(final file) { MessageDigest digest = MessageDigest.getInstance("MD5") file.withInputStream(){ is

我希望使用java或groovy获得完整目录的md5校验和

我必须将源目录复制到目标目录,对源目录和目标目录进行校验,然后删除源目录

我发现这个脚本用于文件,但如何对目录执行相同的操作

import java.security.MessageDigest

def generateMD5(final file) {
    MessageDigest digest = MessageDigest.getInstance("MD5")
    file.withInputStream(){ is ->
        byte[] buffer = new byte[8192]
        int read = 0
        while( (read = is.read(buffer)) > 0) {
            digest.update(buffer, 0, read);
        }
    }
    byte[] md5sum = digest.digest()
    BigInteger bigInt = new BigInteger(1, md5sum)

    return bigInt.toString(16).padLeft(32, '0')
}

有更好的方法吗?

不清楚获取目录的md5sum意味着什么。您可能需要文件列表的校验和;您可能需要文件列表及其内容的校验和。如果您已经对文件数据本身进行了求和,我建议您为目录列表指定一个明确的表示形式(注意文件名中的有害字符),然后每次计算并散列它。您还需要考虑如何处理UNIX世界中的特殊文件(套接字、管道、设备和Simulink);NTFS具有文件流,并且我相信也有类似于SysLink的一些东西。

< P>我在目录中计算MD5校验和的功能:

首先,我使用的是FastMD5:

这是我的密码:

  def MD5HashDirectory(String fileDir) {
    MD5 md5 = new MD5();
    new File(fileDir).eachFileRecurse{ file ->
      if (file.isFile()) {
        String hashFile = MD5.asHex(MD5.getHash(new File(file.path)));
        md5.Update(hashFile, null);
      }

    }
    String hashFolder = md5.asHex();
    return hashFolder
  }

HashCopy是一个Java应用程序。它可以在单个文件或目录上递归地生成和验证MD5和SHA。我不确定它是否有API。它可以从www.jdxsoftware.org下载。

我有同样的要求,并选择我的“目录哈希”作为目录中所有(非目录)文件的连接流的MD5哈希。正如crozin在上的评论中提到的,您可以使用
SequenceInputStream
作为连接其他流负载的流。我使用的是MD5算法

基本上,通过目录树递归,为非目录文件的
向量添加
FileInputStream
实例
Vector
然后方便地使用
elements()
方法来提供
枚举
,而
SequenceInputStream
需要循环。对于MD5算法,这只是一个
InputStream

一个问题是,您需要每次都以相同的顺序显示文件,以使哈希与相同的输入相同。
File
中的
listFiles()
方法不能保证排序,所以我按文件名排序

我是为SVN控制的文件这样做的,并且希望避免散列隐藏的SVN文件,所以我实现了一个标志来避免隐藏的文件

相关基本代码如下所示。(显然,它可能会“硬化”。)

import org.apache.commons.codec.digest.DigestUtils;
导入java.io.*;
导入java.util.*;
公共字符串calcMD5HashForDir(文件dirToHash,布尔includeHiddenFiles){
断言(dirToHash.isDirectory());
向量fileStreams=新向量();
System.out.println(“找到散列文件:”);
collectInputStreams(dirToHash、fileStreams、includeHiddenFiles);
SequenceInputStream seqStream=
新的SequenceInputStream(fileStreams.elements());
试一试{
字符串md5Hash=DigestUtils.md5Hex(seqStream);
seqStream.close();
返回md5Hash;
}
捕获(IOE异常){
抛出新的RuntimeException(“读取要散列的文件时出错”
+dirToHash.getAbsolutePath(),e);
}
}
私有void collectInputStreams(文件目录,
列出数据流,
布尔值includeHiddenFiles){
File[]fileList=dir.listFiles();
sort(文件列表,//需要以可复制的顺序
新比较器(){
公共整数比较(文件f1,文件f2){
返回f1.getName().compareTo(f2.getName());
}
});
对于(文件f:文件列表){
如果(!includeHiddenFiles&&f.getName().startsWith(“.”){
//跳过它
}
else if(f.isDirectory()){
collectInputStreams(f、foundStreams、IncludeHiddenFile);
}
否则{
试一试{
System.out.println(“\t”+f.getAbsolutePath());
添加(新文件输入流(f));
}
catch(filenotfounde异常){
抛出新的断言错误(例如getMessage()
+“:永远找不到文件!”);
}
}
}
}
基于的答案,但正确处理干净的代码和隐藏文件:

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

import java.io.*;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Vector;

public class Hashing {
    public static String hashDirectory(String directoryPath, boolean includeHiddenFiles) throws IOException {
        File directory = new File(directoryPath);
        
        if (!directory.isDirectory()) {
            throw new IllegalArgumentException("Not a directory");
        }

        Vector<FileInputStream> fileStreams = new Vector<>();
        collectFiles(directory, fileStreams, includeHiddenFiles);

        try (SequenceInputStream sequenceInputStream = new SequenceInputStream(fileStreams.elements())) {
            return DigestUtils.md5Hex(sequenceInputStream);
        }
    }

    private static void collectFiles(File directory, List<FileInputStream> fileInputStreams,
                                     boolean includeHiddenFiles) throws IOException {
        File[] files = directory.listFiles();

        if (files != null) {
            Arrays.sort(files, Comparator.comparing(File::getName));

            for (File file : files) {
                if (includeHiddenFiles || !Files.isHidden(file.toPath())) {
                    if (file.isDirectory()) {
                        collectFiles(file, fileInputStreams, includeHiddenFiles);
                    } else {
                        fileInputStreams.add(new FileInputStream(file));
                    }
                }
            }
        }
    }
}
import org.apache.commons.codec.digest.DigestUtils;
导入java.io.*;
导入java.nio.file.Files;
导入java.util.array;
导入java.util.Comparator;
导入java.util.List;
导入java.util.Vector;
公共类散列{
公共静态字符串哈希目录(字符串目录路径,布尔includeHiddenFiles)引发IOException{
文件目录=新文件(目录路径);
如果(!directory.isDirectory()){
抛出新的IllegalArgumentException(“不是目录”);
}
向量fileStreams=新向量();
收集文件(目录、文件流,包括隐藏文件);
try(SequenceInputStream SequenceInputStream=new SequenceInputStream(fileStreams.elements())){
返回DigestUtils.md5Hex(sequenceInputStream);
}
}
私有静态文件(文件目录、列表fileInputStreams、,
布尔includeHiddenFiles)引发IOException{
File[]files=目录.listFiles();
如果(文件!=null){
sort(文件,Comparator.comparing(文件::getName));
用于(文件:文件){
if(includeHiddenFiles | |!Files.ishiden(file.toPath())){
if(file.isDirectory()){
收集文件(文件、文件输入流,包括隐藏文件);
}否则{
添加(新的FileInputStream(文件));
}
}
import org.apache.commons.codec.digest.DigestUtils;

import java.io.*;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Vector;

public class Hashing {
    public static String hashDirectory(String directoryPath, boolean includeHiddenFiles) throws IOException {
        File directory = new File(directoryPath);
        
        if (!directory.isDirectory()) {
            throw new IllegalArgumentException("Not a directory");
        }

        Vector<FileInputStream> fileStreams = new Vector<>();
        collectFiles(directory, fileStreams, includeHiddenFiles);

        try (SequenceInputStream sequenceInputStream = new SequenceInputStream(fileStreams.elements())) {
            return DigestUtils.md5Hex(sequenceInputStream);
        }
    }

    private static void collectFiles(File directory, List<FileInputStream> fileInputStreams,
                                     boolean includeHiddenFiles) throws IOException {
        File[] files = directory.listFiles();

        if (files != null) {
            Arrays.sort(files, Comparator.comparing(File::getName));

            for (File file : files) {
                if (includeHiddenFiles || !Files.isHidden(file.toPath())) {
                    if (file.isDirectory()) {
                        collectFiles(file, fileInputStreams, includeHiddenFiles);
                    } else {
                        fileInputStreams.add(new FileInputStream(file));
                    }
                }
            }
        }
    }
}
import java.security.MessageDigest
import java.io.File

def calcDirHash(fileDir) {
  def hash = MessageDigest.getInstance("SHA-512")
  new File(fileDir).eachFileRecurse{ file ->
    if (file.isFile()) {
      file.eachByte 4096, {bytes, size ->
        hash.update(bytes, 0, size);
      }
    }
  }
  return hash.digest().encodeHex()
}
def sources = fileTree('rootDir').matching {
    include 'src/*', 'build.gradle'
}.sort { it.name }
def digest = MessageDigest.getInstance('SHA-1')
sources.each { digest.update(it.bytes) }
digest.digest().encodeHex().toString()
MD5
SHA-1
SHA-256