568

I am looking to use Java to get the MD5 checksum of a file. I was really surprised but I haven't been able to find anything that shows how to get the MD5 checksum of a file.

How is it done?

erickson
  • 265,237
  • 58
  • 395
  • 493
Jack
  • 20,735
  • 11
  • 48
  • 48
  • 1
    Maybe [this](http://www.devdaily.com/java/jwarehouse/hsqldb/src/org/hsqldb/lib/MD5.java.shtml "MD5 Java") will help. You could also look up the spec but that would take more doing as it's complicated. – waynecolvin Nov 20 '08 at 03:49
  • 4
    Keep in mind that according to the recent research "MD5 should be considered cryptographically broken and unsuitable for further use". http://en.wikipedia.org/wiki/MD5 – Zakharia Stanley May 03 '13 at 01:06
  • 97
    MD5 is no longer considered cryptographically secure, but it's still sufficient for validating file consistency and it's faster than SHA. – jiggy Jun 30 '13 at 22:12
  • 4
    @ZakhariaStanley This is a question about checksumming. – iPherian May 03 '17 at 19:26
  • 2
    The canonical use for MD5 checksums on files is to avoid hostile replacements of distributed files. That's where it is unsecure. But in a scenario where hostile exploits are not a concern, it's perfectly suitable. – Keith Tyler Oct 04 '18 at 00:05

22 Answers22

608

There's an input stream decorator, java.security.DigestInputStream, so that you can compute the digest while using the input stream as you normally would, instead of having to make an extra pass over the data.

MessageDigest md = MessageDigest.getInstance("MD5");
try (InputStream is = Files.newInputStream(Paths.get("file.txt"));
     DigestInputStream dis = new DigestInputStream(is, md)) 
{
  /* Read decorated stream (dis) to EOF as normal... */
}
byte[] digest = md.digest();
erickson
  • 265,237
  • 58
  • 395
  • 493
  • 5
    I agree, very elegant way to calculate the checksum on the fly if you're already doing something with the bytes (i.e. reading them in on from an HTTP connection). – Marc Novakowski Dec 06 '08 at 01:51
  • +1 for stream implementation. @Marc doesn't have to just be an HTTP stream, java io streams come in about every flavor one can think of; i.e. this method would be handy in a wide variety of scenarios. – arkon Jun 09 '12 at 07:24
  • Tried it but, this error occurs Type mismatch: cannot convert from DigestInputStream to FileInputStream why it does not work on my side? I am running on java 1.6 – Al Phaba Dec 17 '12 at 15:25
  • 2
    @AlPhaba Did you declare the `is` as an `InputStream` or a `FileInputStream`? Sounds like you used `FileInputStream`, which would cause this error. – erickson Dec 17 '12 at 17:16
  • Is it possible to use this approach for multiple types of digests? For example, if I need both the `MD5` and `SHA1`? – carlspring Oct 10 '13 at 14:51
  • @carlspring In conjunction with a "tee" input stream, you could. It's not terribly difficult to write one yourself, or use Apache Commons. Here's a [question about that.](http://stackoverflow.com/questions/18801901/) – erickson Oct 10 '13 at 17:36
  • @erickson, I've actually started a question here: http://stackoverflow.com/questions/19300774/calculate-multiple-checksums-from-the-same-inputstream-using-digestinputstream . If you have some time, perhaps you could illustrate it for me? – carlspring Oct 10 '13 at 17:42
  • 1
    @barwnikk It works fine in Java 8. `MethodNotFound` is not an exception from standard Java; perhaps you are talking about a compiler error? In any case, if it doesn't work for you, it's a local configuration problem, or a problem with other code. – erickson Jun 23 '14 at 18:45
  • 4
    @barwnikk Again, that is your local configuration problem. This is valid Java 7 and Java 8 code. If you are stuck with tools from 2006, you'll have to adapt. – erickson Jul 07 '14 at 15:41
  • 5
    @erickson You are not updating the MessageDigest object with the file content. Rt ? This code will print always a same digest. – sunil Oct 31 '14 at 08:16
  • 1
    @sunil No. The `MessageDigest` object is updated by the `DigestInputStream`, with all of the data in the file. It will return the same digest only if the file contents are identical (or there's a hash collision, which is practically impossible unless someone exploits the weakness in MD5 intentionally). – erickson Nov 01 '14 at 03:24
  • 1
    @erickson You were right erickson. I forgot to read the content so that the MessageDigest object is updated. I updated your answer with this change. – sunil Nov 02 '14 at 06:26
  • 1
    @erickson I was wondering why this function kept returning the same hash, but it seems your last edit (Nov 3) broke the code again. The part "while(dis.read()!= -1); dis.close();" should be executed in order to return the right md5. – Symen Timmermans Oct 21 '15 at 10:15
  • @SymenTimmermans Thanks for catching that. My edit should fix that. – erickson Oct 21 '15 at 16:02
  • IMO, it's unnecessary in this case to close `is`, as closing `dis` automatically closes `dis`. So, you can move `InputStream is = Files.newInputStream(Paths.get("file.txt"))` out of the `try (...)` (i.e. like this: `MessageDigest md = MessageDigest.getInstance("MD5"); InputStream is = Files.newInputStream(Paths.get("file.txt")); try (DigestInputStream dis = new DigestInputStream(is, md)) {...}`). Although, I'm not sure about coding style (maybe, some style guideline requires both `is` and `dis` to be inside `try (...)` -- but it isn't required by the program logic per se). – Sasha Jun 16 '16 at 18:24
  • Or like this: `MessageDigest md = MessageDigest.getInstance("MD5"); try (DigestInputStream is = new DigestInputStream(Files.newInputStream(Paths.get("file.txt")), md)) {...} byte[] digest = md.digest();`. – Sasha Jun 16 '16 at 18:28
  • @Sasha What if creation of the digest stream raises an exception? Then the file input stream will not be closed in a timely manner. On the other hand, what harm is there in clearly enforcing the underlying file input stream is to be closed on exiting the `try` block? I don't see any value in this micro-optimization. – erickson Jun 17 '16 at 05:26
  • @erickson, "what if creation of the digest stream raises an exception" -- AFAIK, it can't. "I don't see any value in this micro-optimization" -- you're right, there's no value, it's just a matter of code style. (I just wanted to point out that it's not mandatory to close underlying stream, as it's automatically closed by wrapper stream -- it maybe non-obvious for Java-newcomers.) – Sasha Jun 17 '16 at 09:49
  • But which variable contains MD-5 hash in the end? – gstackoverflow Nov 20 '17 at 08:19
  • @gstackoverflow The variable `digest`, at the end. – erickson Nov 20 '17 at 16:14
  • Its always returning the same result. – Anmol Singh Jaggi May 24 '19 at 07:08
  • @AnmolSinghJaggi You have to actually read the whole stream inside the `try` block. If your code is not working, you could open your own question with an [mcve] to see where your bug is. – erickson May 24 '19 at 12:37
  • Ahh I see now.. Missed it as was in a hurry. You should probably fill in that code as well. – Anmol Singh Jaggi May 24 '19 at 12:59
  • @AnmolSinghJaggi Well, the idea behind the Decorator pattern is that any code that works with an `InputStream` will function with this extension, and compute the digest as a side-effect of whatever processing you are normally doing (like uploading the file, parsing it, etc.). I don’t know what processing people will use, so I can’t do their (whole) job for them. – erickson May 24 '19 at 13:04
  • Does this method consume a lot of memory while calculating MD5 for a large file? Is it recommended if my application is already in serious memory condition? – Wayne Wei Jun 09 '20 at 10:17
  • 1
    @WayneWei No. MD5 hash is a constant space algorithm. It only keeps 16 bytes of state for computation. The implementation might use a 64 byte block buffer internally. – erickson Jun 09 '20 at 15:33
340

Use DigestUtils from Apache Commons Codec library:

try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
    String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}
Leif Gruenwoldt
  • 13,561
  • 5
  • 60
  • 64
  • 1
    Doesn't work for me in my android code I get this error...java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString at org.apache.commons.codec.digest.DigestUtils.md5Hex(DigestUtils.java:215) – JPM May 01 '12 at 21:03
  • @JPM Presume you downloaded and put the `commons-codec.jar` on your classpath already? – Leif Gruenwoldt May 01 '12 at 21:07
  • yes there and I exported in my android project..I can step through the code and the class is there in the source files...weird, must be some android Eclipse issue. – JPM May 01 '12 at 21:08
  • 1
    I had the same problem, but it fixed by this code ` FileInputStream fis = new FileInputStream(new File(filePath)); byte data[] = org.apache.commons.codec.digest.DigestUtils.md5(fis); char md5Chars[] = Hex.encodeHex(data); String md5 = String.valueOf(md5Chars);` – Dmitry_L Jul 17 '13 at 10:45
  • 3
    Nice! For new projects I always think twice before adding a new dependency but for existing project I just have to check if the library is already there to use it. +1 – OscarRyz Jul 31 '13 at 20:45
  • Very nice! Works in MATLAB too... Simply read the file 'fis' and use 'md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(fis);' – Tom Anderson Feb 21 '16 at 06:32
  • Works well and should be the accepted answer, as the accepted answer is not complete. – Arturas M Oct 01 '16 at 17:29
  • Works for me, but seems to be a little bit slower then the accepted answer. – Thomas P Apr 23 '21 at 13:10
176

There's an example at Real's Java-How-to using the MessageDigest class.

Check that page for examples using CRC32 and SHA-1 as well.

import java.io.*;
import java.security.MessageDigest;

public class MD5Checksum {

   public 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();
   }

   // see this How-to for a faster way to convert
   // a byte array to a HEX string
   public static String getMD5Checksum(String filename) throws Exception {
       byte[] b = createChecksum(filename);
       String result = "";

       for (int i=0; i < b.length; i++) {
           result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
       }
       return result;
   }

   public static void main(String args[]) {
       try {
           System.out.println(getMD5Checksum("apache-tomcat-5.5.17.exe"));
           // output :
           //  0bb2827c5eacf570b6064e24e0e6653b
           // ref :
           //  http://www.apache.org/dist/
           //          tomcat/tomcat-5/v5.5.17/bin
           //              /apache-tomcat-5.5.17.exe.MD5
           //  0bb2827c5eacf570b6064e24e0e6653b *apache-tomcat-5.5.17.exe
       }
       catch (Exception e) {
           e.printStackTrace();
       }
   }
}
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
93

The com.google.common.hash API offers:

  • A unified user-friendly API for all hash functions
  • Seedable 32- and 128-bit implementations of murmur3
  • md5(), sha1(), sha256(), sha512() adapters, change only one line of code to switch between these, and murmur.
  • goodFastHash(int bits), for when you don't care what algorithm you use
  • General utilities for HashCode instances, like combineOrdered / combineUnordered

Read the User Guide (IO Explained, Hashing Explained).

For your use-case Files.hash() computes and returns the digest value for a file.

For example a digest calculation (change SHA-1 to MD5 to get MD5 digest)

HashCode hc = Files.asByteSource(file).hash(Hashing.sha1());
"SHA-1: " + hc.toString();

Note that is much faster than , so use if you do not need a cryptographically secure checksum. Note also that should not be used to store passwords and the like since it is to easy to brute force, for passwords use , or instead.

For long term protection with hashes a Merkle signature scheme adds to the security and The Post Quantum Cryptography Study Group sponsored by the European Commission has recommended use of this cryptography for long term protection against quantum computers (ref).

Note that has a higher collision rate than the others.

oluies
  • 17,694
  • 14
  • 74
  • 117
  • What part of Files.hash as stated above does not cover Files.hash ? – oluies Feb 25 '15 at 22:57
  • 2
    The `Files.hash()` is marked as deprecated, the recommended way is: `Files.asByteSource(file).hash(Hashing.sha1())` – erkfel Dec 15 '17 at 20:53
  • 1
    And as of January 2018 `Hashing.sha1()` is marked deprecated. The function `Hashing.sha256()` is recommended instead. [source](https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/hash/Hashing.html#sha1--) – MagicLegend Mar 20 '18 at 11:28
84

Using nio2 (Java 7+) and no external libraries:

byte[] b = Files.readAllBytes(Paths.get("/path/to/file"));
byte[] hash = MessageDigest.getInstance("MD5").digest(b);

To compare the result with an expected checksum:

String expected = "2252290BC44BEAD16AA1BF89948472E8";
String actual = DatatypeConverter.printHexBinary(hash);
System.out.println(expected.equalsIgnoreCase(actual) ? "MATCH" : "NO MATCH");
assylias
  • 321,522
  • 82
  • 660
  • 783
  • @Arash yes absolutely - thanks. I mixed up the JDK Files class and Guava's. – assylias May 23 '16 at 10:30
  • I like this solution more than erickson's since it can be wrapped with Optionals to use pure Functional style programming – Gabriel Hernandez Sep 24 '18 at 16:19
  • 13
    For a big file this will use a lot of memory since the whole file is read and then fed to the digest instead of reading chunks and "digesting" them as they are read. – bernie Dec 03 '18 at 17:00
45

Guava now provides a new, consistent hashing API that is much more user-friendly than the various hashing APIs provided in the JDK. See Hashing Explained. For a file, you can get the MD5 sum, CRC32 (with version 14.0+) or many other hashes easily:

HashCode md5 = Files.hash(file, Hashing.md5());
byte[] md5Bytes = md5.asBytes();
String md5Hex = md5.toString();

HashCode crc32 = Files.hash(file, Hashing.crc32());
int crc32Int = crc32.asInt();

// the Checksum API returns a long, but it's padded with 0s for 32-bit CRC
// this is the value you would get if using that API directly
long checksumResult = crc32.padToLong();
ColinD
  • 108,630
  • 30
  • 201
  • 202
34

Ok. I had to add. One line implementation for those who already have Spring and Apache Commons dependency or are planning to add it:

DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file))

For and Apache commons only option (credit @duleshi):

DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))

Hope this helps someone.

MickJ
  • 2,127
  • 3
  • 20
  • 34
  • 1
    It's `DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))` – duleshi Aug 07 '15 at 06:34
  • David Onter commons based solution is better because it doesn't read a whole file into memory. – Fran Marzoa Mar 18 '18 at 01:12
  • At least for `Spring 5` you have `DigestUtils.md5Digest(InputStream inputStream)` to calculate the MD5 digest and `DigestUtils.md5DigestAsHex(InputStream inputStream)` for hexadecimal string representation of the MD5 digest methods without read a whole file into memory. – Mike Shauneu Sep 20 '18 at 02:58
27

A simple approach with no third party libraries using Java 7

String path = "your complete file path";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(Files.readAllBytes(Paths.get(path)));
byte[] digest = md.digest();

If you need to print this byte array. Use as below

System.out.println(Arrays.toString(digest));

If you need hex string out of this digest. Use as below

String digestInHex = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println(digestInHex);

where DatatypeConverter is javax.xml.bind.DatatypeConverter

sunil
  • 6,444
  • 1
  • 32
  • 44
14

I recently had to do this for just a dynamic string, MessageDigest can represent the hash in numerous ways. To get the signature of the file like you would get with the md5sum command I had to do something like the this:

try {
   String s = "TEST STRING";
   MessageDigest md5 = MessageDigest.getInstance("MD5");
   md5.update(s.getBytes(),0,s.length());
   String signature = new BigInteger(1,md5.digest()).toString(16);
   System.out.println("Signature: "+signature);

} catch (final NoSuchAlgorithmException e) {
   e.printStackTrace();
}

This obviously doesn't answer your question about how to do it specifically for a file, the above answer deals with that quiet nicely. I just spent a lot of time getting the sum to look like most application's display it, and thought you might run into the same trouble.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Brian Gianforcaro
  • 26,564
  • 11
  • 58
  • 77
  • The signature is the digest in hexadecimal format. I too found the hexadecimal representation to work where, as you say, other representations do not work. Thank you for putting this up. – amit kumar Oct 12 '09 at 09:33
  • 1
    This is good, but `.toString(16)` will throw away leading zeros. `String.format("%032x", ...)` may be better. – Harold Jun 10 '20 at 15:37
13
public static void main(String[] args) throws Exception {
    MessageDigest md = MessageDigest.getInstance("MD5");
    FileInputStream fis = new FileInputStream("c:\\apache\\cxf.jar");

    byte[] dataBytes = new byte[1024];

    int nread = 0;
    while ((nread = fis.read(dataBytes)) != -1) {
        md.update(dataBytes, 0, nread);
    };
    byte[] mdbytes = md.digest();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < mdbytes.length; i++) {
        sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
    }
    System.out.println("Digest(in hex format):: " + sb.toString());
}

Or you may get more info http://www.asjava.com/core-java/java-md5-example/

Jam
  • 131
  • 1
  • 2
10

We were using code that resembles the code above in a previous post using

...
String signature = new BigInteger(1,md5.digest()).toString(16);
...

However, watch out for using BigInteger.toString() here, as it will truncate leading zeros... (for an example, try s = "27", checksum should be "02e74f10e0327ad868d138f2b4fdd6f0")

I second the suggestion to use Apache Commons Codec, I replaced our own code with that.

LarsH
  • 27,481
  • 8
  • 94
  • 152
btakashi
  • 111
  • 1
  • 4
  • 1
    Wow, I was looking into an issue where the MD5 stuff was working perfectly for everything, except a file was giving us only a 31 hex digit output, and was failing the md5checksums. that truncating of leading 0s is a huge pain... Thanks for your note. – Mike Mar 01 '12 at 18:11
9

Very fast & clean Java-method that doesn't rely on external libraries:

(Simply replace MD5 with SHA-1, SHA-256, SHA-384 or SHA-512 if you want those)

public String calcMD5() throws Exception{
        byte[] buffer = new byte[8192];
        MessageDigest md = MessageDigest.getInstance("MD5");

        DigestInputStream dis = new DigestInputStream(new FileInputStream(new File("Path to file")), md);
        try {
            while (dis.read(buffer) != -1);
        }finally{
            dis.close();
        }

        byte[] bytes = md.digest();

        // bytesToHex-method
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }

        return new String(hexChars);
}
David
  • 382
  • 3
  • 10
9
public static String MD5Hash(String toHash) throws RuntimeException {
   try{
       return String.format("%032x", // produces lower case 32 char wide hexa left-padded with 0
      new BigInteger(1, // handles large POSITIVE numbers 
           MessageDigest.getInstance("MD5").digest(toHash.getBytes())));
   }
   catch (NoSuchAlgorithmException e) {
      // do whatever seems relevant
   }
}
F.X
  • 159
  • 1
  • 2
9

Here is a handy variation that makes use of InputStream.transferTo() from Java 9, and OutputStream.nullOutputStream() from Java 11. It requires no external libraries and does not need to load the entire file into memory.

public static String hashFile(String algorithm, File f) throws IOException, NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance(algorithm);

    try(BufferedInputStream in = new BufferedInputStream((new FileInputStream(f)));
        DigestOutputStream out = new DigestOutputStream(OutputStream.nullOutputStream(), md)) {
        in.transferTo(out);
    }

    String fx = "%0" + (md.getDigestLength()*2) + "x";
    return String.format(fx, new BigInteger(1, md.digest()));
}

and

hashFile("SHA-512", Path.of("src", "test", "resources", "some.txt").toFile());

returns

"e30fa2784ba15be37833d569280e2163c6f106506dfb9b07dde67a24bfb90da65c661110cf2c5c6f71185754ee5ae3fd83a5465c92f72abd888b03187229da29"
BillRobertson42
  • 12,602
  • 4
  • 40
  • 57
8
String checksum = DigestUtils.md5Hex(new FileInputStream(filePath));
Laurel
  • 5,965
  • 14
  • 31
  • 57
Ravikiran kalal
  • 1,050
  • 8
  • 11
6

Standard Java Runtime Environment way:

public String checksum(File file) {
  try {
    InputStream fin = new FileInputStream(file);
    java.security.MessageDigest md5er =
        MessageDigest.getInstance("MD5");
    byte[] buffer = new byte[1024];
    int read;
    do {
      read = fin.read(buffer);
      if (read > 0)
        md5er.update(buffer, 0, read);
    } while (read != -1);
    fin.close();
    byte[] digest = md5er.digest();
    if (digest == null)
      return null;
    String strDigest = "0x";
    for (int i = 0; i < digest.length; i++) {
      strDigest += Integer.toString((digest[i] & 0xff) 
                + 0x100, 16).substring(1).toUpperCase();
    }
    return strDigest;
  } catch (Exception e) {
    return null;
  }
}

The result is equal of linux md5sum utility.

gotozero
  • 395
  • 4
  • 11
6

Here is a simple function that wraps around Sunil's code so that it takes a File as a parameter. The function does not need any external libraries, but it does require Java 7.

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.xml.bind.DatatypeConverter;

public class Checksum {

    /**
     * Generates an MD5 checksum as a String.
     * @param file The file that is being checksummed.
     * @return Hex string of the checksum value.
     * @throws NoSuchAlgorithmException
     * @throws IOException
     */
    public static String generate(File file) throws NoSuchAlgorithmException,IOException {

        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        messageDigest.update(Files.readAllBytes(file.toPath()));
        byte[] hash = messageDigest.digest();

        return DatatypeConverter.printHexBinary(hash).toUpperCase();
    }

    public static void main(String argv[]) throws NoSuchAlgorithmException, IOException {
        File file = new File("/Users/foo.bar/Documents/file.jar");          
        String hex = Checksum.generate(file);
        System.out.printf("hex=%s\n", hex);            
    }


}

Example output:

hex=B117DD0C3CBBD009AC4EF65B6D75C97B
stackoverflowuser2010
  • 38,621
  • 48
  • 169
  • 217
  • This all nice when you use small files. For a 5gb file you'd be reading all of it into RAM, and as the docs state `It is not intended for reading in large files.` – Lorenzo Mar 30 '22 at 16:48
6

Another implementation: Fast MD5 Implementation in Java

String hash = MD5.asHex(MD5.getHash(new File(filename)));
Lukasz R.
  • 2,265
  • 1
  • 24
  • 22
3

Google guava provides a new API. Find the one below :

public static HashCode hash(File file,
            HashFunction hashFunction)
                     throws IOException

Computes the hash code of the file using hashFunction.

Parameters:
    file - the file to read
    hashFunction - the hash function to use to hash the data
Returns:
    the HashCode of all of the bytes in the file
Throws:
    IOException - if an I/O error occurs
Since:
    12.0
3

If you're using ANT to build, this is dead-simple. Add the following to your build.xml:

<checksum file="${jarFile}" todir="${toDir}"/>

Where jarFile is the JAR you want to generate the MD5 against, and toDir is the directory you want to place the MD5 file.

More info here.

Matt Brock
  • 5,337
  • 1
  • 27
  • 26
2
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();
}
XXX
  • 8,996
  • 7
  • 44
  • 53
1

Pulling together ideas from other answers, here's simple code with no third party dependencies (or DatatypeConverter which is longer in the latest JDKs) that generates this as a hex string compatible with output of the md5sum tool:

import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
...

static String calculateMD5(String path) throws IOException
{
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(Files.readAllBytes(Paths.get(path)));
        return String.format("%032x", new BigInteger(1, md.digest())); // hex, padded to 32 chars
    } catch (NoSuchAlgorithmException ex)
    {
        throw new RuntimeException(ex); // MD5 is always available so this should be impossible
    }
}
Ben Spiller
  • 477
  • 4
  • 12