关于文件夹内容变动对比
现在手机程序很多支持省流量更新,也就是更新时只把改动的文件替换掉。要做到这样,就得能够对两次的文件夹进行对比,于是写了下面对比代码。
package mapcomp.comp; import java.io.File; import java.io.FileInputStream; import java.math.BigInteger; import java.security.MessageDigest; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class Comp { public static void main(String[] args) { comp("E:/comp/po1", "E:/comp/po2"); } public static void comp(String path1, String path2){ List<String> list1 = new ArrayList<String>(); getFileNameList(new File(path1), list1); Map<String, FileInfo> map1 = getFileInfoMap(path1, list1, true); List<String> list2 = new ArrayList<String>(); getFileNameList(new File(path2), list2); Map<String, FileInfo> map2 = getFileInfoMap(path2, list2, false); //MD5计算比较费时,先对比大小,一样再比较md5 Set<String> set1_add = new HashSet<String>(map1.keySet()); Set<String> set2_remove = new HashSet<String>(map2.keySet()); Set<String> set3_common = new HashSet<String>(map1.keySet()); set3_common.addAll(map2.keySet()); set1_add.removeAll(map2.keySet()); System.out.println("新增的文件有:" + set1_add.toString()); set2_remove.removeAll(map1.keySet()); System.out.println("移除的文件有:" + set2_remove.toString()); set3_common.removeAll(set1_add); set3_common.removeAll(set2_remove); System.out.println("保留的文件有:" + set3_common.toString()); //接下来对比保留的文件 //先对比大小,若不一样则肯定不一样,一样然后对比md5 List<String> unSame = new ArrayList<String>(); for(String ph : set3_common){ FileInfo info1 = map1.get(ph); FileInfo info2 = map2.get(ph); if(info1.length != info2.length){ unSame.add(ph); }else{ info2.md5 = getFileMD5(new File(path2 + ph)); if(!info1.md5.equals(info2.md5)){ unSame.add(ph); } } } System.out.println("不一样的文件有:" + unSame.toString()); } //把文件信息整理放到Map private static Map<String, FileInfo> getFileInfoMap(String rootPath, List<String> list1, boolean md5) { Map<String, FileInfo> map = new HashMap<String, FileInfo>(); for(String path : list1){ FileInfo info = new FileInfo(); File file = new File(path); info.filePath = file.getAbsolutePath().substring(rootPath.length()); info.length = file.length(); if(md5){ info.md5 = getFileMD5(file); } map.put(info.filePath, info); } return map; } public static String getFileMD5(File file) { if (!file.exists() || !file.isFile()) { return null; } MessageDigest digest = null; FileInputStream in = null; byte buffer[] = new byte[1024]; int len; try { digest = MessageDigest.getInstance("MD5"); in = new FileInputStream(file); while ((len = in.read(buffer, 0, 1024)) != -1) { digest.update(buffer, 0, len); } in.close(); } catch (Exception e) { e.printStackTrace(); return null; } BigInteger bigInt = new BigInteger(1, digest.digest()); return bigInt.toString(16); } //获取所有文件 public static void getFileNameList(File folder, List<String> list){ File[] listFiles = folder.listFiles(); for(File f : listFiles){ if(f.isDirectory()){ getFileNameList(f, list); }else{ list.add(f.getAbsolutePath()); } } } } class FileInfo{ public String filePath; public long length; public String md5; }
这只是大致思路,可以在把新代码作为path1,检出的信息以某种格式作为文件,在需要更新升级的地方进行同样的整理对比,然后把需要更新的信息传送回来,然后发送过去替换。当年在东软那个项目升级完全可以这样来,竟然采取的是全部文件打包发送替换,一个项目差不多一个g,给服务器增加了巨大压力。