使用RandomAccessFile获取文件的MD5值

不同于使用FileInputStream和FileOutputStream读写文件,RadomAccessFile支持随机访问文件的方式。下面是官方的解释:
Allows reading from and writing to a file in a random-access manner. 
This is different from the uni-directional sequential access that a {@link FileInputStream} or {@link FileOutputStream} provides. 
If the file is opened in read/write mode, write operations are available as well. 
The position of the next read or write operation can be moved forwards and backwards after every operation.

如何使用RandomAccessFile获取文件的MD5值:
1.通过MessageDigest.getInstance("MD5")得到MessageDigest实例。
2.创建RadomAccessFile的一个实例。
3.通过RadomAccessFile.read()读取文件,并调用MessageDigest.update()更新MessageDigest。
4.将MessageDigest转化为16进制的字符串(即MD5值)。

以下是相关代码:
public class MD5Util {
    private static final int STREAM_BUFFER_LENGTH = 1024;
    private static MessageDigest messagedigest = null;

    static{
        try{
            messagedigest = MessageDigest.getInstance("MD5");
        }catch(NoSuchAlgorithmException e){
            System.err.println(String.format("Initialization error , MessageDigest is not support %s : %s",
                    MD5Util.class.getName(),e.getMessage()));
        }
    }

    /**
    *获取一般文件的md5值
    */
    public static String getFileMD5(String path){
        File file = new File(path);
        if (!file.exists() || !file.isFile()) {
            return null;
        }
        byte[] buffer = new byte[STREAM_BUFFER_LENGTH * 8];
        RandomAccessFile rf = null;
        int len;
        try{
            rf = new RandomAccessFile(path,"r");
            while ((len = rf.read(buffer)) != -1){
                messagedigest.update(buffer,0,len);
            }
        }catch (IOException e){
            System.err.println(String.format("Class %s File %s can not read : %s",
                    MD5Util.class.getName(), file.getAbsolutePath(),e.getMessage()));
        }finally {
            if(rf != null){
                try{
                    rf.close();
                }catch (IOException e){
                    System.err.println(String.format("Class %s File %s's RandomAccessFile can not close : %s",
                            MD5Util.class.getName(), file.getAbsolutePath(),e.getMessage()));
                }
            }
        }
        BigInteger integer = new BigInteger(1, messagedigest.digest());
        return integer.toString(16);
    }
但是要计算上G文件的MD5时,计算时间大约要几秒,用户体验肯定不好。对此,可以通过计算大文件的几个特定部分来表示大文件的MD5值(但不是大文件的MD5值)。

相关代码如下:
public static String getSimpleMD5(String path) {
        File file = new File(path);
        if (!file.exists() || !file.isFile()) {
            return null;
        }
        int len;
        RandomAccessFile rf = null;
        byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
        try {
            rf = new RandomAccessFile(path, "r");
            if (file.length() > STREAM_BUFFER_LENGTH * 3) {
                //开头读取一个KB
                rf.seek(0);
                rf.read(buffer);
                messagedigest.update(buffer);

                //文件中间开始读取一个KB
                rf.seek(file.length() / 2);
                rf.read(buffer);
                messagedigest.update(buffer);

                //文件结尾前读取一个KB
                rf.seek(file.length() - STREAM_BUFFER_LENGTH);
                rf.read(buffer);
                messagedigest.update(buffer);
            } else {
                while ((len = rf.read(buffer)) != -1) {
                    messagedigest.update(buffer, 0, len);
                }
            }
        } catch (IOException e) {
            System.err.println(String.format("Class %s File %s can not read : %s",MD5Util.class.getName(), file.getAbsolutePath(), e.getMessage()));
        } finally {
            if (rf != null) {
                try {
                    rf.close();
                } catch (IOException e) {
                    System.err.println(String.format("Class %s File %s's RandomAccessFile can not close : %s",MD5Util.class.getName(), file.getAbsolutePath(), e.getMessage()));
                }
            }
        }
        BigInteger integer = new BigInteger(1, messagedigest.digest());
        return integer.toString(16);
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值