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

package comcollection.test;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.CRC32;

import org.apache.commons.io.FileUtils;

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

public class DiffUtils {

    public static void scanFileDirectory(String sourceFileUrl, String currentFileUrl, String diffFileUrl) {
        // 1. 在diffUrl目录下,创建日期格式的文件夹,用于存放改动的文件
        // 1.1 获取当前日期
        String nowTime = createCurrentTime();
        // 1.2创建日期形式的文件目录
        File fileDire = new File(diffFileUrl, nowTime);
        fileDire.mkdirs();
        String diffFilePath = fileDire.getAbsolutePath();
        // 2,遍历出删除的信息,并记录到删除日志文件中
        // 2.1创建删除日志文件
        String rootPath = fileDire.getAbsolutePath();
        File deleteLogFile = new File(rootPath, "delete.log");
        try {
            deleteLogFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 2.2遍历出删除的信息
        HashMap<String, Long> sourceUrlMap = getAllFileMap(sourceFileUrl);
        HashMap<String, Long> currentUrlMap = getAllFileMap(currentFileUrl);
        List<String> deleteFiles = new ArrayList<String>();
        String deleteCurrentTime = createCurrentTime();
        String diffMessage = "-------- Diff时间:" + deleteCurrentTime + " --------";
        try {
            FileUtils.writeStringToFile(deleteLogFile, diffMessage + "\n", "UTF-8", true);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        long start = System.currentTimeMillis();
        int delFilecount = 0;
        for (Map.Entry<String, Long> sourceEntry : sourceUrlMap.entrySet()) {
            // 遍历原版本目录下的文件,如果该文件不在当前版本目录下面,即该文件被删除了
            if (!currentUrlMap.containsKey(sourceEntry.getKey())) {
                deleteFiles.add(sourceEntry.getKey());
                delFilecount++;
            }
        }
        long end = System.currentTimeMillis();
        // 2.3 删除的信息记录到删除日志文件中
        String fileCount = "-------- 共删除文件" + delFilecount + "个--------";
        String endContent = "-------- 运行完毕,耗时:" + (end - start) + "ms";
        try {
            FileUtils.writeLines(deleteLogFile, "UTF-8", deleteFiles, true);
            FileUtils.write(deleteLogFile, fileCount + "\n", "UTF-8", true);
            FileUtils.write(deleteLogFile, endContent + "\n", "UTF-8", true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 3.将所有新增与更新信息记录到更新日志文件中
        // 3.1 创建新增/更新日志文件
        File updateAndAddLogFile = new File(rootPath, "updateAndAdd.log");
        try {
            updateAndAddLogFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 3.2遍历新增与更新记录,并存入到集合中
        List<String> addFiles = new ArrayList<String>();
        List<String> updateFiles = new ArrayList<String>();
        /**
         * addOrUpdateFileUrls的key-value分别为currentFileUrl文件的全路径名、
         * diffFileUrl文件的全路径名 通过文件的完全路径可以获得文件对象,用于后面的文件复制操作
         */
        Map<String, String> addOrUpdateFileUrls = new HashMap<String, String>();
        int addCount = 0;
        int updateCount = 0;
        long fileAddOrUpdatestart = System.currentTimeMillis();
        for (Map.Entry<String, Long> currentUrlMapEntry : currentUrlMap.entrySet()) {
            String currentUrlSuffix = currentUrlMapEntry.getKey();
            // 如果元素存在原来的目录下,并且crc相同,就是更新操作
            if (sourceUrlMap.containsKey(currentUrlMapEntry.getKey())) {
                try {
                    long sourceUrlCrc = sourceUrlMap.get(currentUrlMapEntry.getKey());
                    long currentUrlCrc = currentUrlMapEntry.getValue();
                    if (currentUrlCrc != sourceUrlCrc) {
                        updateCount++;
                        updateFiles.add(currentUrlSuffix);
                        addOrUpdateFileUrls.put(currentFileUrl + currentUrlSuffix, diffFilePath + currentUrlSuffix);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            } else {// 如果元素不存在A目录下,就是新增的元素
                addCount++;
                addFiles.add(currentUrlSuffix);
                addOrUpdateFileUrls.put(currentFileUrl + currentUrlSuffix, diffFilePath + currentUrlSuffix);
            }
        }
        long fileAddOrUpdateend = System.currentTimeMillis();
        String fileAddOrUpdate = "-------- 运行完毕,耗时:" + (fileAddOrUpdateend - fileAddOrUpdatestart) + "ms";
        // 3.3写入日志文件
        String addAndUpdateCurrentTime = createCurrentTime();
        String addAndUpdateDiffMessage = "-------- Diff时间:" + addAndUpdateCurrentTime + " --------";
        String updateCountMessage = "-------- 共更新文件" + updateCount + "个 -------";
        String addCountMessage = "-------- 共新增文件" + addCount + "个 -------";
        try {
            FileUtils.writeStringToFile(updateAndAddLogFile, addAndUpdateDiffMessage + "\n", "UTF-8", true);
            FileUtils.writeStringToFile(updateAndAddLogFile, updateCountMessage + "\n", "UTF-8", true);
            FileUtils.writeLines(updateAndAddLogFile, "UTF-8", updateFiles, true);
            FileUtils.writeStringToFile(updateAndAddLogFile, addCountMessage + "\n", "UTF-8", true);
            FileUtils.writeLines(updateAndAddLogFile, "UTF-8", addFiles, true);
            FileUtils.writeStringToFile(updateAndAddLogFile, fileAddOrUpdate + "\n", "UTF-8", true);
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        // 4.将有新增/修改的文件放入第三个目录中
        for (Map.Entry<String, String> addOrUpdateEntry : addOrUpdateFileUrls.entrySet()) {
            String filePath = addOrUpdateEntry.getValue();
            File diffFile = new File(addOrUpdateEntry.getValue());
            String fileDirs = filePath.replace(diffFile.getName(), "");
            File creFileDir = new File(fileDirs);
            creFileDir.mkdirs();
            FileChannel inputChannel = null;
            FileChannel outputChannel = null;
            FileInputStream fileInputStream = null;
            FileOutputStream fileOutputStream = null;
            try {
                fileInputStream = new FileInputStream(new File(addOrUpdateEntry.getKey()));
                inputChannel = fileInputStream.getChannel();
                fileOutputStream = new FileOutputStream(diffFile);
                outputChannel = fileOutputStream.getChannel();
                outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    inputChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    outputChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 获取yyyy年MM月dd日HH点mm分ss秒格式的当前时间
     * 
     * @return
     */
    private static String createCurrentTime() {
        Date now = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日HH点mm分ss秒");
        String nowTime = dateFormat.format(now);
        return nowTime;
    }

    /**
     * 将获取到的文件存到map中
     * 
     * @param path
     * @return
     */
    private static HashMap<String, Long> getAllFileMap(String DirectoryUrl) {

        List<File> allFileList = new ArrayList<File>();
        HashMap<String, Long> resMap = new HashMap<String, Long>();

        allFileList = getAllFile(new File(DirectoryUrl), allFileList);
        for (File file : allFileList) {
            resMap.put(file.getAbsolutePath().replace(DirectoryUrl, ""), getFileCRC(file));
        }
        return resMap;
    }

    /**
     * 递归遍历所有文件
     * 
     * @param file
     * @param allFileList
     * @return
     */
    private static List<File> getAllFile(File file, List<File> allFileList) {
        if (file.exists()) {
            if (file.isDirectory()) {
                File f[] = file.listFiles();
                for (File tempFile : f) {
                    getAllFile(tempFile, allFileList);
                }
            } else {
                allFileList.add(file);
            }
        }
        return allFileList;
    }

    /**
     * 获取文件的CRC
     * 
     * @param file
     * @return
     * @throws IOException
     */
    private static long getFileCRC(File file) {
        BufferedInputStream bsrc = null;
        CRC32 crc = new CRC32();
        try {
            bsrc = new BufferedInputStream(new FileInputStream(file));
            byte[] bytes = new byte[1024];
            int i;
            while ((i = bsrc.read(bytes)) != -1) {
                crc.update(bytes, 0, i);
            }
        } catch (Exception e) {

        } finally {
            if (bsrc != null) {
                try {
                    bsrc.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return crc.getValue();
    }
}

测试代码如下:

package comcollection.test;

import org.junit.Test;

/**
 * @author MJC
 *2018年4月25日
 * 上午8:55:26
 */
public class DiffUtilsTest {

    private static final String oldUrl = "C:\\Users\\jljd\\Desktop\\diff工具需求说明及示例\\diff工具需求说明及示例\\A";
    private static final String newUrl = "C:\\Users\\jljd\\Desktop\\diff工具需求说明及示例\\diff工具需求说明及示例\\B";
    private static final String diffUrl = "C:\\Users\\jljd\\Desktop\\diff工具需求说明及示例\\diff工具需求说明及示例\\change";
    
    @Test
    public void scanFileDirectory(){
        DiffUtils.scanFileDirectory(oldUrl, newUrl, diffUrl);
    }
}

 

posted @ 2018-04-25 18:50  代码改变心态  阅读(281)  评论(0编辑  收藏  举报