脚本宝典收集整理的这篇文章主要介绍了md5 大文件,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
测试 mail.rar , 一个1.59GB 的大文件,结果如下: // 分别测试3次,下面是测试结果; 我的电脑是 Intel i5 4核, 8G 内存; 不运行此程序且 不做任何操作 的时候, 观察发现: cpu 10%, mem 70% // md5ByJavaIO , 观察发现,大概的平均是: cpu 35%, mem 71% // md5:8ba6b147475af653bc4609d4cDF72148 time:74s 74s 74s; 测试N多次都是74s, 非常稳定
// md5ByFileChannel , 观察发现,大概的平均是: cpu 31%, mem 71% // md5:8ba6b147475af653bc4609d4cdf72148 time:75s 72s 73s
// md5ByFileChannelAndMapPEdByteBuffer , 观察发现,大概的平均是: cpu 30%, mem 71% // md5:8ba6b147475af653bc4609d4cdf72148 time:52s 53s 54s
// fastMd5 , 观察发现,大概的平均是: cpu 31%, mem 80% // md5:8ba6b147475af653bc4609d4cdf72148 time:51s 52s 51s
// 实际计算时间的时候, 需要减去休眠的100 * 10, 即1s,
代码如下:
import com.twmacinta.util.MD5;import com.twmacinta.util.MD5OutputStream;import java.io.*;import java.nio.ByteBuffer;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;import java.securITy.MessageDigest;import java.security.NoSuchAlgorithmException;public class MD5Util { /** * 默认的密码字符串组合,apache校验下载的文件的正确性用的就是默认的这个组合 */ PRotected static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; protected static MessageDigest messagedigest = null; static { try { messagedigest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException nSAEx) { System.err.println(MD5Util.class.getName() + "初始化失败,MessageDigest不支持MD5Util。"); nsaex.printStackTrace(); } } public static void main(String[] args) throws IOException { long begin = System.currentTimeMillis(); File Big = new File("D:\office2013破解版.ISO"); // 810M// big = new File("C:\Users\xd\Desktop\工作重要资料\xxx.zip"); // 2.25G; 但不能超过2G, 否则 at java.base/sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:994) big = new File("D:\lk\mail.rar");// 1.59G String md5 = null; // 获取文件的 md5; 如果是仅仅是获取字符串的md5, 当然不需要这么复杂。。 for (int i = 0; i < 10; i++) {// md5 = md5ByJavaIO(big); // java io 的方式// md5 = md5ByFileChannel(big); // java nio 的方式// md5 = md5ByFileChannelAndMappedByteBuffer(big); // fast md5 md5 = fastMd5(big); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } long end = System.currentTimeMillis(); System.out.println("md5:" + md5 + " time:" + ((end - begin) / 1000) + "s"); // 分别测试3次,下面是测试结果; 我的电脑是 intel i5 4核, 8G 内存; 不运行此程序且 不做任何操作 的时候, 观察发现: cpu 10%, mem 70% // md5ByJavaIO , 观察发现,大概的平均是: cpu 35%, mem 71% // md5:8ba6b147475af653bc4609d4cdf72148 time:74s 74s 74s; 测试N多次都是74s, 非常稳定 // md5ByFileChannel , 观察发现,大概的平均是: cpu 31%, mem 71% // md5:8ba6b147475af653bc4609d4cdf72148 time:75s 72s 73s // md5ByFileChannelAndMappedByteBuffer , 观察发现,大概的平均是: cpu 30%, mem内存几乎毫无增长; SSD是 读300M/S; 写入220K-2M // md5:8ba6b147475af653bc4609d4cdf72148 time:52s 53s 54s // fastMd5 , 观察发现,大概的平均是: cpu 开始有个高峰,后面趋于平稳,后面是30% ; 大概是80%, mem xxx % // md5:8ba6b147475af653bc4609d4cdf72148 time:51s 52s 51s // 实际计算时间的时候, 需要减去休眠的100 * 10, 即1s, } /** * 适用于上G大的文件 * * @param file * @return * @throws IOException */ public static String md5ByFileChannelAndMappedByteBuffer(File file) throws IOException { FileinputStream in = new FileInputStream(file); FileChannel ch = in.getChannel(); MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); messagedigest.update(byteBuffer); in.close(); return bufferToHex(messagedigest.digest()); } private static String md5ByFileChannel(File big) { if (big == null) { return null; } MessageDigest md; FileInputStream inputStream = null; try { int read = 0; inputStream = new FileInputStream(big); md = MessageDigest.getInstance("MD5"); FileChannel channel = inputStream.getChannel(); ByteBuffer buff = ByteBuffer.allocate(2048); while (channel.read(buff) != -1) { buff.flip(); md.update(buff); buff.clear(); } return bufferToHex(md.digest()); } catch (NoSuchAlgorithmException e) { return null; } catch (IOException e) { return null; } finally { try { if (inputStream != null) inputStream.close(); } catch (IOException e) { } } } // private String generateMD5(SequenceInputStream inputStream){ private static String md5ByJavaIO(File big) { if (big == null) { return null; } MessageDigest md; InputStream inputStream = null; try { int read = 0; inputStream = new FileInputStream(big); byte[] buf = new byte[2048]; md = MessageDigest.getInstance("MD5"); while ((read = inputStream.read(buf)) > 0) { md.update(buf, 0, read); } return bufferToHex(md.digest()); } catch (NoSuchAlgorithmException e) { return null; } catch (IOException e) { return null; } finally { try { if (inputStream != null) inputStream.close(); } catch (IOException e) {// ... } } } private static String fastMd5(File big) { String md5Str = null; try { MD5OutputStream out = new MD5OutputStream(new com.twmacinta.io.NullOutputStream()); InputStream in = new BufferedInputStream(new FileInputStream(big)); byte[] buf = new byte[65536];// 65536 是最佳数值, 大于或小于这个数字都会 导致耗时增加, 不知道为什么.. int num_read; long total_read = 0; while ((num_read = in.read(buf)) != -1) { total_read += num_read; out.write(buf, 0, num_read); } md5Str = MD5.asHex(out.hash()); //System.out.println(md5Str + " " + big); in.close(); out.close(); } catch (Exception e) { e.printStackTrace(); } return md5Str; } public static String getMD5String(String s) { return getMD5String(s.getBytes()); } public static String getMD5String(byte[] bytes) { messagedigest.update(bytes); return bufferToHex(messagedigest.digest()); } private static String bufferToHex(byte bytes[]) { return bufferToHex(bytes, 0, bytes.length); } private static String bufferToHex(byte bytes[], int m, int n) { StringBuffer stringbuffer = new StringBuffer(2 * n); int k = m + n; for (int l = m; l < k; l++) { appendHexpair(bytes[l], stringbuffer); } return stringbuffer.toString(); } private static void appendHexPair(byte BT, StringBuffer stringbuffer) { char c0 = hexDigits[(bt & 0xf0) >> 4]; char c1 = hexDigits[bt & 0xf]; stringbuffer.append(c0); stringbuffer.append(c1); } public static boolean checkPassword(String password, String md5PwdStr) { String s = getMD5String(password); return s.equals(md5PwdStr); }}
可见,大文件的时候, 最好还是不要java IO到内存, 可能映射过程就需要比较久时间。NIO MPP是很好的选择。
另外, 我们是否可以继续提高 大文件md5 的计算速度呢? 据说 多线程分块校验。。
我感觉行不通;
另外,这边使用了一个 fastMD5的库, 发现确实可以稍微提升一点速度。 fastMD5 主要作用,大概是 不要NIO, 直接普通FIleInputStream 即可。
以上是脚本宝典为你收集整理的md5 大文件全部内容,希望文章能够帮你解决md5 大文件所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。