• 编写一个diff工具,用于判断两个目录下所有的改动 --1.0版本


    需求说明:

    编写一个diff工具,用于判断两个目录下所有的改动

    详细介绍:

    1. AB两个目录,目录所在位置及层级均不确定
    2. 需要以B为基准找出两个目录中所有有改动的文件(文件或内容增加、修改、删除),将有改动的文件放入第三个目录中,层级结构与原目录相同
    3. 将所有新增与更新信息记录到更新日志文件中
    4. 将删除信息单独记录到删除日志文件中
    5. 每次执行diff工具需要生成一个新的以日期命名目录存放文件

    使用场景:

    本工具用于软件版本升级时找出两个版本间所有修改过的文件,便于增量替换。

    提示:

    1. 使用CRC判断文件是否改动
    2. 控制台日志记录使用slf4j增删日志可以使用其他方式记录
    3. 部分jar包已提供,如需使用到新的jar包可自行添加
      1 package comcollection.test;
      2 
      3 import java.io.BufferedInputStream;
      4 import java.io.File;
      5 import java.io.FileInputStream;
      6 import java.io.FileOutputStream;
      7 import java.io.IOException;
      8 import java.nio.channels.FileChannel;
      9 import java.text.SimpleDateFormat;
     10 import java.util.ArrayList;
     11 import java.util.Date;
     12 import java.util.HashMap;
     13 import java.util.List;
     14 import java.util.Map;
     15 import java.util.zip.CRC32;
     16 import org.apache.commons.io.FileUtils;
     17 
     18 /**
     19  * @author MJC 2018年4月24日 上午23:53:45
     20  */
     21 public class DiffUtils {
     22 
     23     private static void writeToFile(File file, String content, String charbyte) {
     24         try {
     25             FileUtils.write(file, content + "
    ", "UTF-8", true);
     26         } catch (IOException e) {
     27             e.printStackTrace();
     28         }
     29     }
     30 
     31     @SuppressWarnings("resource")
     32     public static void judgeFileChange(String oldUrl, String newUrl, String diffUrl) {
     33 
     34         FileChannel inputChannel = null;
     35         FileChannel outputChannel = null;
     36         HashMap<String, File> filesMap = getFilesUpdateAndAddMap(oldUrl, newUrl);
     37 
     38         // 创建diffUrl对应的根目录
     39         File fileDir = new File(diffUrl);
     40         fileDir.mkdirs();
     41 
     42         Date now = new Date();
     43         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日HH点mm分ss秒");
     44         String nowTime = dateFormat.format(now);
     45         diffUrl = diffUrl + "\" + nowTime + "\";
     46         File fileDire = new File(diffUrl);
     47         fileDire.mkdirs();
     48 
     49         // 创建delete.log、updateAndAdd.log日志文件
     50         String deleteLog = diffUrl + "delete.log";
     51         String updateAndAddLog = diffUrl + "updateAndAdd.log";
     52         File deleteLogFile = null;
     53         File updateAndAddLogFile = null;
     54         deleteLogFile = new File(deleteLog);
     55         updateAndAddLogFile = new File(updateAndAddLog);
     56 
     57         // 遍历删除文件、并且将信息写入日志文件
     58         String timeUrl = "-------- Diff时间:" + nowTime + " --------";
     59         writeToFile(deleteLogFile, timeUrl, "UTF-8");
     60         List<String> oldUrlFilePaths = getAllFilePaths(oldUrl);
     61         List<String> newUrlFilePaths = getAllFilePaths(newUrl);
     62         int count = 0;
     63         long start = System.currentTimeMillis(); // 获取开始时间
     64         for (String filePath : oldUrlFilePaths) {
     65             if (!newUrlFilePaths.contains(filePath)) {
     66                 count++;
     67                 writeToFile(deleteLogFile, filePath, "UTF-8");
     68             }
     69         }
     70         long end = System.currentTimeMillis(); // 获取结束时间
     71         String fileCount = "-------- 共删除文件" + count + "--------";
     72         writeToFile(deleteLogFile, fileCount + "
    ", "UTF-8");
     73         String endContent = "-------- 运行完毕,耗时:" + (end - start) + "ms";
     74         writeToFile(deleteLogFile, endContent + "
    ", "UTF-8");
     75 
     76         // 遍历新增/更改文件、并且将信息写入日志文件
     77         Date now2 = new Date();
     78         SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy年MM月dd日HH点mm分ss秒");
     79         String nowTime2 = dateFormat2.format(now2);
     80         String timeUrl2 = "-------- Diff时间:" + nowTime2 + " --------";
     81         writeToFile(updateAndAddLogFile, timeUrl2, "UTF-8");
     82         HashMap<String, Long> oldUrlMap = getAllFileMap(oldUrl);
     83         HashMap<String, Long> newUrlMap = getAllFileMap(newUrl);
     84 
     85         for (Map.Entry<String, Long> newUrlMapEntry : newUrlMap.entrySet()) {
     86             // 如果元素存在原来的目录下,并且crc相同,就是更新操作
     87             if (oldUrlMap.containsKey(newUrlMapEntry.getKey())) {
     88                 try {
     89                     long oldUrlCrc = oldUrlMap.get(newUrlMapEntry.getKey());
     90                     long newUrlCrc = newUrlMapEntry.getValue();
     91                     if (oldUrlCrc != newUrlCrc) {
     92                         writeToFile(updateAndAddLogFile, "更新:" + newUrlMapEntry.getKey(), "UTF-8");
     93                     }
     94                 } catch (Exception e) {
     95                     e.printStackTrace();
     96                 }
     97 
     98             } else {// 如果元素不存在A目录下,就是新增的元素
     99                 writeToFile(updateAndAddLogFile, "新增:" + newUrlMapEntry.getKey(), "UTF-8");
    100             }
    101         }
    102         /**
    103          * 将新增、更新的文件copy到diffUrl目录下
    104          */
    105         for (Map.Entry<String, File> addAndUpdate : filesMap.entrySet()) {
    106             // 创建每个文件对应的目录
    107             File file = addAndUpdate.getValue();
    108             String filePath = diffUrl + addAndUpdate.getKey();
    109             String fileDirs = filePath.replace(file.getName(), "");
    110             File creFileDir = new File(fileDirs);
    111             creFileDir.mkdirs();
    112 
    113             try {
    114                 inputChannel = new FileInputStream(file).getChannel();
    115                 outputChannel = new FileOutputStream(new File(filePath)).getChannel();
    116                 outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
    117             } catch (Exception e) {
    118                 e.printStackTrace();
    119             } finally {
    120                 try {
    121                     inputChannel.close();
    122                 } catch (IOException e) {
    123                     e.printStackTrace();
    124                 }
    125                 try {
    126                     outputChannel.close();
    127                 } catch (IOException e) {
    128                     e.printStackTrace();
    129                 }
    130             }
    131         }
    132     }
    133 
    134     /**
    135      * 获取新增/更新文件-用于遍历出file文件,以便复制操作引用此方法
    136      * 
    137      * @param oldUrl
    138      * @param newUrl
    139      * @return
    140      */
    141     private static HashMap<String, File> getFilesUpdateAndAddMap(String oldUrl, String newUrl) {
    142         HashMap<String, File> oldUrlMap = getAllFileMaps(oldUrl);
    143         HashMap<String, File> newUrlMap = getAllFileMaps(newUrl);
    144         HashMap<String, File> addAndUpdateMap = new HashMap<String, File>();
    145         for (Map.Entry<String, File> newUrlEntry : newUrlMap.entrySet()) {
    146             // 如果元素存在A目录下,且crc相同,就是更新
    147             if (oldUrlMap.containsKey(newUrlEntry.getKey())) {
    148                 try {
    149                     long oldFileCrc = getFileCRC(oldUrlMap.get(newUrlEntry.getKey()));
    150                     long newFileCrc = getFileCRC(newUrlEntry.getValue());
    151                     if (oldFileCrc != newFileCrc) {
    152                         addAndUpdateMap.put(newUrlEntry.getKey(), newUrlEntry.getValue());
    153                     }
    154                 } catch (Exception e) {
    155                     e.printStackTrace();
    156                 }
    157 
    158             } else {// 如果元素不存在A目录下,就是新增的元素
    159                 addAndUpdateMap.put(newUrlEntry.getKey(), newUrlEntry.getValue());
    160             }
    161         }
    162         return addAndUpdateMap;
    163     }
    164 
    165     /**
    166      * 遍历所有文件-- map的value类型为File形式
    167      * 
    168      * @param path
    169      * @return
    170      */
    171     private static HashMap<String, File> getAllFileMaps(String path) {
    172 
    173         List<File> allFileList = new ArrayList<File>();
    174         HashMap<String, File> resMap = new HashMap<String, File>();
    175 
    176         allFileList = getAllFile(new File(path), allFileList);
    177         for (File file : allFileList) {
    178             resMap.put(file.getAbsolutePath().replace(path, ""), file);
    179         }
    180         return resMap;
    181     }
    182 
    183     /**
    184      * 遍历所有文件-- map的value类型为long形式的CRC 该路径去掉url前缀
    185      * 
    186      * @param path
    187      * @return
    188      */
    189     private static HashMap<String, Long> getAllFileMap(String url) {
    190 
    191         List<File> allFileList = new ArrayList<File>();
    192         HashMap<String, Long> resMap = new HashMap<String, Long>();
    193 
    194         allFileList = getAllFile(new File(url), allFileList);
    195         for (File file : allFileList) {
    196             resMap.put(file.getAbsolutePath().replace(url, ""), getFileCRC(file));
    197         }
    198         return resMap;
    199     }
    200 
    201     /**
    202      * 遍历该目录下的所有文件对应的路径(截取 path之后的路径)
    203      * 
    204      * @param path
    205      * @return
    206      */
    207     private static List<String> getAllFilePaths(String path) {
    208 
    209         List<File> allFileList = new ArrayList<File>();
    210         List<String> allFilePaths = new ArrayList<String>();
    211 
    212         allFileList = getAllFile(new File(path), allFileList);
    213         for (File file : allFileList) {
    214             allFilePaths.add(file.getAbsolutePath().replace(path, ""));
    215         }
    216 
    217         return allFilePaths;
    218     }
    219 
    220     /**
    221      * 遍历该目录下的所有文件
    222      * 
    223      * @param file
    224      * @param allFileList
    225      * @return
    226      */
    227     private static List<File> getAllFile(File file, List<File> allFileList) {
    228         if (file.exists()) {
    229             // 如果当前对象是文件夹,递归调用此方法,获取目录下的所有文件
    230             if (file.isDirectory()) {
    231                 File f[] = file.listFiles();
    232                 for (File tempFile : f) {
    233                     getAllFile(tempFile, allFileList);
    234                 }
    235             } else {
    236                 // 如果当前对象是个文件,将文件存到list中
    237                 allFileList.add(file);
    238             }
    239         }
    240         return allFileList;
    241     }
    242 
    243     /**
    244      * 获取文件的CRC
    245      * 
    246      * @param file
    247      * @return
    248      * @throws IOException
    249      */
    250     private static long getFileCRC(File file) {
    251         BufferedInputStream bsrc = null;
    252         CRC32 crc = new CRC32();
    253         try {
    254             bsrc = new BufferedInputStream(new FileInputStream(file));
    255             byte[] bytes = new byte[1024];
    256             int i;
    257             while ((i = bsrc.read(bytes)) != -1) {
    258                 crc.update(bytes, 0, i);
    259             }
    260         } catch (Exception e) {
    261 
    262         } finally {
    263             if (bsrc != null) {
    264                 try {
    265                     bsrc.close();
    266                 } catch (IOException e) {
    267                     e.printStackTrace();
    268                 }
    269             }
    270         }
    271         return crc.getValue();
    272     }
    273 }
     1 package comcollection.test;
     2 
     3 
     4 import org.junit.Test;
     5 
     6 /**
     7  * @author MJC 2018年4月24日 上午23:53:45
     8  */
     9 public class DiffUtilsTest {
    10     private static final String oldUrl = "C:\Users\jljd\Desktop\diff工具需求说明及示例\diff工具需求说明及示例\A";
    11     private static final String newUrl = "C:\Users\jljd\Desktop\diff工具需求说明及示例\diff工具需求说明及示例\B";
    12     private static final String diffUrl = "C:\Users\jljd\Desktop\diff工具需求说明及示例\diff工具需求说明及示例\change";
    13     
    14     @Test
    15     public void testjudgeFileChange(){
    16         DiffUtils7.judgeFileChange(oldUrl, newUrl, diffUrl);
    17     }
    18 
    19 }
    纸上学来终觉浅,觉知此事需躬行
  • 相关阅读:
    DPDK 多进程
    dpdk helloword
    dpdk-ring-ping
    【基于python实现UI自动化】3.0 selenium
    算法题:实现 strStr()函数
    python程序设计:某体操比赛共有10名运动员参加,12名评委将根据运动员表现进行评分(满分10分),请编写Python程序,解决下列问题:
    Scrapy框架实战(五):通用爬虫 CrawlSpider
    python爬虫爬取_高德地图_主要城市迁徙意愿排行榜_19年至今数据
    年轻就该多尝试,教你20小时Get一项新技能
    LeetCode:283.移动零——简单
  • 原文地址:https://www.cnblogs.com/dreamHighMjc/p/8935100.html
Copyright © 2020-2023  润新知