简体   繁体   中英

How to get a file directory's MD5 checksum in Android/Java

I want to get an MD5 checksum of a file directory, I have already get the algorithm for a file, but it results null when I use it to a directory. How can I get the checksum quickly. The following are my algotithm for a file(Edited from the anonymous stackoverflower).

public String fileToMD5(String filePath) {
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(filePath); // Create an FileInputStream instance according to the filepath
            byte[] buffer = new byte[1024]; // The buffer to read the file
            MessageDigest digest = MessageDigest.getInstance("MD5"); // Get a MD5 instance
            int numRead = 0; // Record how many bytes have been read
            while (numRead != -1) {
                numRead = inputStream.read(buffer);
                if (numRead > 0)
                    digest.update(buffer, 0, numRead); // Update the digest
            }
            byte [] md5Bytes = digest.digest(); // Complete the hash computing
            return convertHashToString(md5Bytes); // Call the function to convert to hex digits
        } catch (Exception e) {
            return null;
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close(); // Close the InputStream
                } catch (Exception e) { }
            }
        }
    }

I searched that there are some solutings:

  1. Pre-order the files under the directory.
  2. Compress the directory into an archive file such as .zip or .rar, and checksum it.
  3. Get all the content under the directory into a stream, and checksum it.

I wonder whether there are some convenient solutions.Thank you in advance.

I just did this, but I did it for a directory that I knew was going to be flat (no subdirectories)

  • Iterate through directory files
  • Get MD5 of each file
  • Append that MD5 to a String
  • After I was done iterating through the files, I got the MD5 of the string the contained all the other files' MD5s

This has the affect that if any of the files were to change, this "directory" md5 would also change.

I know there are the other ways, including the ones you mentioned (like zipping it) but this is the route I chose.

Edit: I had to do get a folder AND it's subfolders md5 and this is how I accomplished that.

NOTE: I used Google's Guava lib for the hashing

NOTE: The way my code is written, it WILL change if the order of files in the directory changes

public static String generateMD5(String dir)
{
    File[] files = new File(dir).listFiles();
    return Hashing.md5().hashString(expandFiles(files, ""), Charsets.UTF_8).toString();
} 

/* Recursive folder expansion */
public static String expandFiles(File[] dirFiles, String md5in)
{
    String md5out = md5in;
    for(File file : dirFiles)
    { 

        if(file.isHidden()) //For my uses, I wanted to skip any hidden files (.DS_Store was being a problem on a mac)
        {
            System.out.println("We have skipped this hidden file: " + file.getName());
        } 
        else if (file.isDirectory())
        {
            System.out.println("We are entering a directory recursively: " + file.getName());
            md5out += Hashing.md5().hashString(expandFiles(file.listFiles(), md5out), Charsets.UTF_8).toString(); //Recursive call, we have found a subdirectory.
            System.out.println("We have gotten the md5 of " + file.getName() + " It is " + md5out);
        }
        else //We found a file
        {
            HashCode md5 = null;
            try
            {
                md5 = Files.hash(file, Hashing.md5());
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            md5out += md5.toString();
            System.out.println("We have just gotten the md5 of a specific file: " + file.getName() + ". This file has the md5 of " + md5out);

        }
    }
    return md5out;

据我所知,没有一种有效的方法来获取目录的校验和。

You need: 1. Calculate md5 of all files in directory 2. Calculate md5 of result from 1 step.

Here is for you

public static String dirMD5(String dir)
{
    String md5    = "";
    File   folder = new File(dir);
    File[] files  = folder.listFiles();

    for (int i=0; i<files.length; i++)
    {
        md5 = md5 + getMd5OfFile(files[i].toString());
    }
    md5 = GetMD5HashOfString(md5);
    return md5;
}


public static String getMd5OfFile(String filePath)
{
    String returnVal = "";
    try 
    {
        InputStream   input   = new FileInputStream(filePath); 
        byte[]        buffer  = new byte[1024];
        MessageDigest md5Hash = MessageDigest.getInstance("MD5");
        int           numRead = 0;
        while (numRead != -1)
        {
            numRead = input.read(buffer);
            if (numRead > 0)
            {
                md5Hash.update(buffer, 0, numRead);
            }
        }
        input.close();

        byte [] md5Bytes = md5Hash.digest();
        for (int i=0; i < md5Bytes.length; i++)
        {
            returnVal += Integer.toString( ( md5Bytes[i] & 0xff ) + 0x100, 16).substring( 1 );
        }
    } 
    catch(Throwable t) {t.printStackTrace();}
    return returnVal.toUpperCase();
}

public static String    GetMD5HashOfString  (String str)
    {
        MessageDigest md5 ;        
        StringBuffer  hexString = new StringBuffer();
        try
        {                            
            md5 = MessageDigest.getInstance("md5");         
            md5.reset();
            md5.update(str.getBytes());                       
            byte messageDigest[] = md5.digest();
            for (int i = 0; i < messageDigest.length; i++)
            {
                hexString.append(Integer.toHexString((0xF0 & messageDigest[i])>>4));
                hexString.append(Integer.toHexString (0x0F & messageDigest[i]));
            }
        } 
        catch (Throwable t) {History.Error(t);}      
        return hexString.toString();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM