快速比较文件内容是否相同

日常工作中,我们经常会用到如下代码片段来进行字符串比较 ,来判断内容是否相同;

 	private boolean equals(String a, String b){
        return a == b || ( a != null && a.equals(b));
    }

该实现能解决大部分情况下的字符串比对,但存在一部分极端情况,例如:入参a和b的对象较大;部分业务场景会要求对两个文件的内容进行比对,判断是否相同!
那么这种比对通过上述代码是否合适呢?

先看下equals的源码,得知它是通过比较字符串的每个字符,来确定两个对象是否相等的。如下所示!

 	public boolean equals(Object anObject) {
	    if (this == anObject) {
	        return true;
	    }
	    if (anObject instanceof String) {
	        String anotherString = (String)anObject;
	        int n = value.length;
	        if (n == anotherString.value.length) {
	            char v1[] = value;
	            char v2[] = anotherString.value;
	            int i = 0;
	            while (n-- != 0) {
	                if (v1[i] != v2[i])
	                    return false;
	                i++;
	            }
	            return true;
	        }
	    }
	    return false;
	}

为了验证字符串内容过大时的性能,我加入了其他两种方式来进行比对,将内容进行MD5或SHA1加密后再进行比较!
以下在内容大小不一的情况所产生的时间对比(运行十次的耗时结果)

字符串内容大小:205K

处理方式 耗时(ms) 平均耗时(ms)
string 9、8、7、5、4、4、4、4、4、6 6.5
md5 4、3、4、3、3、2、6、3、3、2 3.3
sha1 6、8、8、7、3、2、6、2、2、2 4.6

字符串内容大小:1024K

处理方式 耗时(ms) 平均耗时(ms)
string 21、27、17、16、15、16、18、19、20 16.9
md5 12、11、11、10、11、10、15、12、9、8 10.9
sha1 15、10、9、9、9、10、11、9、9、9 10.0

字符串内容大小:3071K

处理方式 耗时(ms) 平均耗时(ms)
string 57、54、71、50、57、50、51、70、82、68 61
md5 31、30、32、25、27、25、31、26、24、26 27.7
sha1 31、32、27、28、27、27、30、30、28、28 28.8

当内容过大时,加密后再进行比对的性能远远超过了直接比对;通过MD5和SHA1加密之后的性能相差无几,看了一下它们的加密原理,由于对算法知识知之甚少,只知他们对内容的加密过程做了很多优化;所以在时间效率上,远远超过了直接比较(即对内容的每个字符进行比对)方式!

测试用例如下:

	public static void main(String[] args) {
	     long sum = 0;
	     for (int i = 0; i < 11; i++) {
	         long start = System.currentTimeMillis();
	         String md5 = getFileSha1("E:\\bidui.txt"); //getMD5Two txt2String getFileSha1
	         String md51 = getFileSha1("E:\\bidui1.txt"); //getMD5Two txt2String getFileSha1
	         boolean result = md51 == md5 || md51.equals(md5);
	         long a = System.currentTimeMillis() - start;
	         sum += a;
	         System.out.println(a);
	     }
	     long avg = sum / 10;
	     System.out.println("平均值:" + avg);
	}

/**
     * 读取txt文件的内容
     *
     * @return 返回文件内容
     */
    public static String txt2String(String path) {
        StringBuilder result = new StringBuilder();
        try {
            BufferedReader br = new BufferedReader(new FileReader(new File(path)));//构造一个BufferedReader类来读取文件
            String s = null;
            while ((s = br.readLine()) != null) {//使用readLine方法,一次读一行
                result.append(s);
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result.toString();
	}

   // 计算文件的 SHA-1 值
    public static String getFileSha1(String path) {

        File file = new File(path);
        if (!file.isFile()) {
            return null;
        }
        MessageDigest digest = null;
        FileInputStream in = null;
        byte buffer[] = new byte[8192];
        int len;
        try {
            digest = MessageDigest.getInstance("SHA-1");
            in = new FileInputStream(file);
            while ((len = in.read(buffer)) != -1) {
                digest.update(buffer, 0, len);
            }
            BigInteger bigInt = new BigInteger(1, digest.digest());
            return bigInt.toString(16);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

	public static String getMD5Two(String path) {
        StringBuffer sb = new StringBuffer("");
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(FileUtils.readFileToByteArray(new File(path)));
            byte b[] = md.digest();
            int d;
            for (int i = 0; i < b.length; i++) {
                d = b[i];
                if (d < 0) {
                    d = b[i] & 0xff;
                    // 与上一行效果等同
                    // i += 256;
                }
                if (d < 16)
                    sb.append("0");
                sb.append(Integer.toHexString(d));
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
	}

你可能感兴趣的:(服务端)