corrected checksum calculation so that files can be deleted shortly after the calculation is completed.

This commit is contained in:
Jeremy Long
2016-10-08 18:05:55 -04:00
parent 110c97bc15
commit 7fc2be6a0a

View File

@@ -23,6 +23,7 @@ import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer; import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.security.MessageDigest; import java.security.MessageDigest;
@@ -49,20 +50,61 @@ public final class Checksum {
/** /**
* <p> * <p>
* Creates the cryptographic checksum of a given file using the specified algorithm.</p> * Creates the cryptographic checksum of a given file using the specified
* algorithm.</p>
* *
* @param algorithm the algorithm to use to calculate the checksum * @param algorithm the algorithm to use to calculate the checksum
* @param file the file to calculate the checksum for * @param file the file to calculate the checksum for
* @return the checksum * @return the checksum
* @throws IOException when the file does not exist * @throws IOException when the file does not exist
* @throws NoSuchAlgorithmException when an algorithm is specified that does not exist * @throws NoSuchAlgorithmException when an algorithm is specified that does
* not exist
*/ */
public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException { public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException {
final MessageDigest digest = MessageDigest.getInstance(algorithm); MessageDigest md = MessageDigest.getInstance(algorithm);
FileInputStream fis = null; FileInputStream fis = null;
FileChannel ch = null;
try { try {
fis = new FileInputStream(file); fis = new FileInputStream(file);
final FileChannel ch = fis.getChannel(); ch = fis.getChannel();
ByteBuffer buf = ByteBuffer.allocateDirect(8192);
int b = ch.read(buf);
while ((b != -1) && (b != 0)) {
buf.flip();
byte[] bytes = new byte[b];
buf.get(bytes);
md.update(bytes, 0, b);
buf.clear();
b = ch.read(buf);
}
return md.digest();
} finally {
if (ch != null) {
try {
ch.close();
} catch (IOException ex) {
LOGGER.trace("Error closing channel '{}'.", file.getName(), ex);
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {
LOGGER.trace("Error closing file '{}'.", file.getName(), ex);
}
}
}
/*
// while the following is likely faster, it does not work as we need to
// be able to delete the file, see
// http://stackoverflow.com/questions/24589488/why-does-this-utility-method-leaves-files-locked
//
final MessageDigest digest = MessageDigest.getInstance(algorithm);
FileInputStream fis = null;
FileChannel ch = null;
try {
fis = new FileInputStream(file);
ch = fis.getChannel();
long remainingToRead = file.length(); long remainingToRead = file.length();
long start = 0; long start = 0;
while (remainingToRead > 0) { while (remainingToRead > 0) {
@@ -79,6 +121,13 @@ public final class Checksum {
start += amountToRead; start += amountToRead;
} }
} finally { } finally {
if (ch != null) {
try {
ch.close();
} catch (IOException ex) {
LOGGER.trace("Error closing channel '{}'.", file.getName(), ex);
}
}
if (fis != null) { if (fis != null) {
try { try {
fis.close(); fis.close();
@@ -88,6 +137,7 @@ public final class Checksum {
} }
} }
return digest.digest(); return digest.digest();
*/
} }
/** /**