如何在Android中为文件生成MD5校验和?
在我的应用程序中,我有一个要求为一个文件生成一个MD5校验和。 你能否告诉我是否有办法达到这个目标?
谢谢。
将文件内容转换为string并使用以下方法:
public static String getMD5EncryptedString(String encTarget){ MessageDigest mdEnc = null; try { mdEnc = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { System.out.println("Exception while encrypting to md5"); e.printStackTrace(); } // Encryption algorithm mdEnc.update(encTarget.getBytes(), 0, encTarget.length()); String md5 = new BigInteger(1, mdEnc.digest()).toString(16); while ( md5.length() < 32 ) { md5 = "0"+md5; } return md5; }
请注意,这种简单的方法适用于较小的string,但对大文件不会有效。 对于后者,请看dentex的答案 。
这段代码来自CyanogenMod 10.2 android ROM的CMupdater。 它testing下载的ROM到更新程序的应用程序。
代码: https : //github.com/CyanogenMod/android_packages_apps_CMUpdater/blob/cm-10.2/src/com/cyanogenmod/updater/utils/MD5.java
它的作用就像一个魅力:
/* * Copyright (C) 2012 The CyanogenMod Project * * * Licensed under the GNU GPLv2 license * * The text of the license can be found in the LICENSE file * or at https://www.gnu.org/licenses/gpl-2.0.txt */ package com.cyanogenmod.updater.utils; import android.text.TextUtils; import android.util.Log; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5 { private static final String TAG = "MD5"; public static boolean checkMD5(String md5, File updateFile) { if (TextUtils.isEmpty(md5) || updateFile == null) { Log.e(TAG, "MD5 string empty or updateFile null"); return false; } String calculatedDigest = calculateMD5(updateFile); if (calculatedDigest == null) { Log.e(TAG, "calculatedDigest null"); return false; } Log.v(TAG, "Calculated digest: " + calculatedDigest); Log.v(TAG, "Provided digest: " + md5); return calculatedDigest.equalsIgnoreCase(md5); } public static String calculateMD5(File updateFile) { MessageDigest digest; try { digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { Log.e(TAG, "Exception while getting digest", e); return null; } InputStream is; try { is = new FileInputStream(updateFile); } catch (FileNotFoundException e) { Log.e(TAG, "Exception while getting FileInputStream", e); return null; } byte[] buffer = new byte[8192]; int read; try { while ((read = is.read(buffer)) > 0) { digest.update(buffer, 0, read); } byte[] md5sum = digest.digest(); BigInteger bigInt = new BigInteger(1, md5sum); String output = bigInt.toString(16); // Fill to 32 chars output = String.format("%32s", output).replace(' ', '0'); return output; } catch (IOException e) { throw new RuntimeException("Unable to process file for MD5", e); } finally { try { is.close(); } catch (IOException e) { Log.e(TAG, "Exception on closing MD5 input stream", e); } } } }
我有相同的任务,这个代码很好:
public static String fileToMD5(String filePath) { InputStream inputStream = null; try { inputStream = new FileInputStream(filePath); byte[] buffer = new byte[1024]; MessageDigest digest = MessageDigest.getInstance("MD5"); int numRead = 0; while (numRead != -1) { numRead = inputStream.read(buffer); if (numRead > 0) digest.update(buffer, 0, numRead); } byte [] md5Bytes = digest.digest(); return convertHashToString(md5Bytes); } catch (Exception e) { return null; } finally { if (inputStream != null) { try { inputStream.close(); } catch (Exception e) { } } } } private static String convertHashToString(byte[] md5Bytes) { String returnVal = ""; for (int i = 0; i < md5Bytes.length; i++) { returnVal += Integer.toString(( md5Bytes[i] & 0xff ) + 0x100, 16).substring(1); } return returnVal.toUpperCase(); }
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(); }
好友尝试下面的代码
MessageDigest md = MessageDigest.getInstance("MD5"); InputStream is = new FileInputStream("file.txt"); try { is = new DigestInputStream(is, md); // read stream to EOF as normal... } finally { is.close(); } byte[] digest = md.digest();
这个方法适用于我,在一个131MB的zip文件。 计算出的MD5与AccuHash( http://www.accuhash.com )在同一文件中计算的结果相匹配
public static String calculateMD5(File updateFile) { MessageDigest digest; try { digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { Log.e("calculateMD5", "Exception while getting Digest", e); return null; } InputStream is; try { is = new FileInputStream(updateFile); } catch (FileNotFoundException e) { Log.e("calculateMD5", "Exception while getting FileInputStream", e); return null; } byte[] buffer = new byte[8192]; int read; try { while ((read = is.read(buffer)) > 0) { digest.update(buffer, 0, read); } byte[] md5sum = digest.digest(); BigInteger bigInt = new BigInteger(1, md5sum); String output = bigInt.toString(16); // Fill to 32 chars output = String.format("%32s", output).replace(' ', '0'); return output; } catch (IOException e) { throw new RuntimeException("Unable to process file for MD5", e); } finally { try { is.close(); } catch (IOException e) { Log.e("calculateMD5", "Exception on closing MD5 input stream", e); } } }
我发现以下工作非常好:
Process process = Runtime.getRuntime().exec("md5 "+fileLocation); BufferedReader inputStream = new BufferedReader(new InputStreamReader(process.getInputStream())); String result = inputStream.readLine().split(" ")[0];
这将调用内置的md5
命令。 variablesfileLocation
将被设置为文件的位置。 当然,我build议在这里build立一些检查来检查文件是否存在。
如果你需要计算大文件的MD5 ,你可以使用这个:
import:
import java.security.MessageDigest;
方法:
private byte[] calculateMD5ofFile(String location) throws IOException, NoSuchAlgorithmException { FileInputStream fs= new FileInputStream(location); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] buffer=new byte[bufferSize]; int bytes=0; do{ bytes=fs.read(buffer,0,bufferSize); if(bytes>0) md.update(buffer,0,bytes); }while(bytes>0); byte[] Md5Sum = md.digest(); return Md5Sum; }
参考: https : //docs.oracle.com/javase/7/docs/api/java/security/MessageDigest.html
将字节数组转换为hex。 用这个
public static String ByteArraytoHexString(byte[] bytes) { StringBuilder hexString = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(bytes[i] & 0xFF); if (hex.length() == 1) { hexString.append('0'); } hexString.append(hex); } return hexString.toString(); }
参考在Java中,如何将字节数组转换为hex数字string,同时保持前导零?