I wrote the following program to calculate SHA-256 hash value of a string in Java:
public class ToHash {
public static void main(String[] args) {
byte[] data = "test".getBytes("UTF8");
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(data);
System.out.println(new BASE64Encoder().encode(hash));
}
}
Well, that works fine. In the next step I want to develop it in a way to accept a file and calculate its hash value. My solution is to read whole the file in a string array and the call the digest()
method on that string array. But there are two problems :
I don't have any idea how to read whole the file into an array? Currently I think I must read it line by line and append an array with the new lines!
Above methodology need a lot of memory for big files!
This is my current program to read a file:
public class ToHash {
public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException, FileNotFoundException, IOException {
// TODO code application logic here
// The name of the file to open.
String fileName = "C:\\Users\\ghasemi\\Desktop\\1.png";
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader(fileName));
while ((sCurrentLine = br.readLine()) != null) {
byte[] data = sCurrentLine.getBytes("UTF8");
System.out.println(new BASE64Encoder().encode(data));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
It seems that there is no method for BufferedReader
object to read whole the file with one call.
You can read the file and calculate the value of the hash as you go.
byte[] buffer= new byte[8192];
int count;
MessageDigest digest = MessageDigest.getInstance("SHA-256");
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName))) {
while ((count = bis.read(buffer)) > 0) {
digest.update(buffer, 0, count);
}
}
byte[] hash = digest.digest();
System.out.println(new BASE64Encoder().encode(hash));
This doesn't assume anything about character sets or about the file fitting into memory, and it doesn't ignore line terminators either.
Or you can use a DigestInputStream.