Java实现两个文件夹之间的增量同步

同步方向:源文件夹--->目标文件夹

改进版:https://blog.csdn.net/qq_46037812/article/details/120183489

思路

1、分别获取两个文件夹的Map<String, File>,fileMap1,fileMap2

2、对比两个Map,将fileMap2相对于fileMap1中缺失的、过时的文件找出来,另存入一个fileMap

3、使用fileMap对目标文件夹进行更新

注意:此同步过程基于文件,若源文件夹中存在空文件夹,则该空文件夹不会进行同步。


获取Map的方法

/**
     *
     * @param file 源文件夹
     * @param fileMap 文件夹中的文件Map
     * @param sourceFilePath 源文件夹路径
     * @return Map
     */
    public static Map<String, File> getFileMap(File file, Map<String, File> fileMap, String sourceFilePath)
    {
        for (int i = 0; i < file.listFiles().length; i++)
        {
            File childFile = file.listFiles()[i];
            if (!childFile.isDirectory()) //如果不是文件夹
            {
                String childPath = childFile.getAbsolutePath(); //获取绝对路径
                String relativePath = childPath.substring(sourceFilePath.length());//从绝对路径中取得相对路径
                fileMap.put(relativePath,childFile);
            }
            else
                getFileMap(childFile, fileMap, sourceFilePath);//递归查询
        }
        return fileMap;
    }

查找差异的方法 

/**
     * 查询两个文件夹中的差异文件个数,将差异文件路径存储在fileMap中
     * @param sourceFile 源文件夹
     * @param destinationFile 目标文件夹
     */
    public static void search(File sourceFile, File destinationFile)
    {
        fileMap1 = getFileMap(sourceFile, fileMap1, sourceFile.getAbsolutePath());
        fileMap2 = getFileMap(destinationFile, fileMap2, destinationFile.getAbsolutePath());

        for (Map.Entry<String, File> entry : fileMap1.entrySet()) //遍历源文件夹的文件
        {
            String key = entry.getKey();
            if (fileMap2.containsKey(key)) //如果目标文件夹中存在此文件
            {
                Date date1 = new Date(entry.getValue().lastModified());
                Date date2 = new Date(fileMap2.get(key).lastModified());
                if (date1.after(date2)) //对比最后修改时间,如果源文件夹中文件较新,则更新
                {
                    fileMap.put(key, entry.getValue());
                }
            }
            else
            {
                fileMap.put(key, entry.getValue());
            }
        }
    }

更新的方法

 /**
     *
     * @param destinationFile 目标文件夹
     */
    public static void change(File destinationFile)
    {
        String destinationFilePath = destinationFile.getAbsolutePath();
        for (Map.Entry<String, File> entry : fileMap.entrySet())
        {
            String key = entry.getKey();
            File file1 = entry.getValue();
            File file2 = new File(destinationFilePath + key);
            if (fileMap2.containsKey(key))
            {
                file2 = fileMap2.get(key);
                file2.delete(); //删除已存在的文件
            }
            try
            {
                file2.getParentFile().mkdirs(); //建立多层文件夹结构
                Files.copy(file1.toPath(), file2.toPath()); //文件复制
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

源码

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class File_Syn
{
    static Map<String, File> fileMap = new HashMap<>();
    static Map<String, File> fileMap1 = new HashMap<>();
    static Map<String, File> fileMap2 = new HashMap<>();
    public static void main(String[] args) {
        new Form();
    }

    /**
     *
     * @param file 源文件夹
     * @param fileMap 文件夹中的文件Map
     * @param sourceFilePath 源文件夹路径
     * @return Map
     */
    public static Map<String, File> getFileMap(File file, Map<String, File> fileMap, String sourceFilePath)
    {
        for (int i = 0; i < file.listFiles().length; i++)
        {
            File childFile = file.listFiles()[i];
            if (!childFile.isDirectory()) //如果不是文件夹
            {
                String childPath = childFile.getAbsolutePath(); //获取绝对路径
                String relativePath = childPath.substring(sourceFilePath.length());//从绝对路径中取得相对路径
                fileMap.put(relativePath,childFile);
            }
            else
                getFileMap(childFile, fileMap, sourceFilePath);//递归查询
        }
        return fileMap;
    }

    /**
     * 查询两个文件夹中的差异文件个数,将差异文件路径存储在fileMap中
     * @param sourceFile 源文件夹
     * @param destinationFile 目标文件夹
     */
    public static void search(File sourceFile, File destinationFile)
    {
        fileMap1 = getFileMap(sourceFile, fileMap1, sourceFile.getAbsolutePath());
        fileMap2 = getFileMap(destinationFile, fileMap2, destinationFile.getAbsolutePath());

        for (Map.Entry<String, File> entry : fileMap1.entrySet()) //遍历源文件夹的文件
        {
            String key = entry.getKey();
            if (fileMap2.containsKey(key)) //如果目标文件夹中存在此文件
            {
                Date date1 = new Date(entry.getValue().lastModified());
                Date date2 = new Date(fileMap2.get(key).lastModified());
                if (date1.after(date2)) //对比最后修改时间,如果源文件夹中文件较新,则更新
                {
                    fileMap.put(key, entry.getValue());
                }
            }
            else
            {
                fileMap.put(key, entry.getValue());
            }
        }
    }

    /**
     *
     * @param destinationFile 目标文件夹
     * @param jTextArea 文本域
     */
    public static void change(File destinationFile,JTextArea jTextArea)
    {
        String destinationFilePath = destinationFile.getAbsolutePath();
        for (Map.Entry<String, File> entry : fileMap.entrySet())
        {
            String key = entry.getKey();
            File file1 = entry.getValue();
            File file2 = new File(destinationFilePath + key);
            if (fileMap2.containsKey(key))
            {
                file2 = fileMap2.get(key);
                file2.delete(); //删除已存在的文件
            }
            try
            {
                file2.getParentFile().mkdirs(); //建立多层文件夹结构
                Files.copy(file1.toPath(), file2.toPath()); //文件复制
            }catch (IOException e) {
                e.printStackTrace();
                jTextArea.setText("同步失败");
            }
            jTextArea.setText("同步完成");
        }
    }
}
class Form extends JFrame
{
    Font font = new Font("宋体",0,20);
    JButton sourceBtn = new JButton("选择源文件夹");
    JButton destinationBtn = new JButton("选择目标文件夹");
    JButton compare = new JButton("对比文件夹");
    JButton change = new JButton("同步");
    JTextArea jTextArea1 = new JTextArea(2,20);
    JTextArea jTextArea2 = new JTextArea(2,20);
    JTextArea result = new JTextArea(2,20);
    JPanel jPanel1 = new JPanel();
    JPanel jPanel2 = new JPanel();
    JPanel jPanel3 = new JPanel();
    JPanel jPanel4 = new JPanel();
    JPanel jPanel5 = new JPanel();
    JFileChooser jFileChooser = new JFileChooser();
    File sourceFilePath = null;
    File destinationFilePath = null;
    Form()
    {
        setSize(300,350);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new GridLayout(5,1));
        setLocationRelativeTo(null);
        setVisible(true);
        jTextArea1.setFont(font);jTextArea1.setLineWrap(true);jTextArea1.setWrapStyleWord(true);
        jTextArea2.setFont(font);jTextArea2.setLineWrap(true);jTextArea2.setWrapStyleWord(true);
        result.setFont(font);result.setLineWrap(true);result.setWrapStyleWord(true);
        jPanel1.add(sourceBtn);jPanel1.add(destinationBtn);
        jPanel2.add(jTextArea1);
        jPanel3.add(jTextArea2);
        jPanel4.add(compare);jPanel4.add(change);
        jPanel5.add(result);
        add(jPanel1);add(jPanel2);add(jPanel3);add(jPanel4);add(jPanel5);
        jFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        sourceBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int returnVal = jFileChooser.showOpenDialog(null);
                if (returnVal == JFileChooser.APPROVE_OPTION)
                {
                    sourceFilePath = jFileChooser.getSelectedFile();
                    jTextArea1.setText(sourceFilePath.getAbsolutePath());
                }
            }
        });
        destinationBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int returnVal = jFileChooser.showOpenDialog(null);
                if (returnVal == JFileChooser.APPROVE_OPTION)
                {
                    destinationFilePath  = jFileChooser.getSelectedFile();
                    jTextArea2.setText(destinationFilePath.getAbsolutePath());
                }
            }
        });
        compare.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (sourceFilePath == null || destinationFilePath == null)
                {
                    result.setText("未选择文件夹");
                    return;
                }
                long start = System.currentTimeMillis();
                File_Syn.search(sourceFilePath,destinationFilePath);
                long finish = System.currentTimeMillis();
                result.setText("查找到"+File_Syn.fileMap.size()+"处差异文件");
                result.append("\n执行耗时:"+(finish-start)+"毫秒");
            }
        });
        change.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (File_Syn.fileMap.isEmpty())
                {
                    result.setText("文件差异列表为空");
                    return;
                }
                long start = System.currentTimeMillis();
                File_Syn.change(destinationFilePath,result);
                long finish = System.currentTimeMillis();
                result.append("\n执行耗时:"+(finish-start)+"毫秒");
                File_Syn.fileMap.clear();
            }
        });
    }
}

运行截图

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Java实现两个系统的部门同步功能可以使用以下步骤: 1. 定义两个系统的 API 接口,用于获取部门信息。 2. 创建 Java 程序,使用这两个系统的 API 接口获取部门信息。 3. 使用 Java 的对象序列化功能,将获取到的两个系统的部门信息序列化为字节数组。 4. 将两个系统的部门信息字节数组进行比较,如果不同则执行同步操作。 5. 同步操作可以使用两个系统的 API 接口进行部门信息的更新。 示例代码如下: ``` import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.List; public class DepartmentSync { private System1API system1API; private System2API system2API; public void sync() throws IOException, ClassNotFoundException { // 获取两个系统的部门信息 List<Department> system1Departments = system1API.getDepartments(); List<Department> system2Departments = system2API.getDepartments(); // 序列化两个系统的部门信息 byte[] system1Data = serialize(system1Departments); byte[] system2Data = serialize(system2Departments); // 比较两个系统的部门信息,如果不同则执行同步操作 if (!java.util.Arrays.equals(system1Data, system2Data)) { system2API.updateDepartments(system1Departments); } } private byte[] serialize(Object object) throws IOException { try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos)) { oos.writeObject( ### 回答2: 使用JAVA实现两个系统的部门同步功能可以通过以下步骤: 1. 首先,需要在两个系统中建立一个共享的数据库或者API接口用来存储和获取部门相关信息。可以使用MySQL或者其他关系型数据库来实现共享数据库,也可以使用RESTful API接口来实现数据的传输。 2. 在JAVA中,可以使用JDBC连接到共享的数据库中,通过执行SQL查询语句来获取部门信息。首先,在每个系统中建立一个部门类,包含部门的ID、名称、描述等属性。然后,使用JDBC连接到数据库并执行对应的查询语句,将查询结果映射到对应的部门类中。 3. 接下来,需要实现数据的同步功能。可以使用定时任务或者消息队列来实现数据的同步。定时任务可以每隔一段时间执行一次同步操作,而消息队列可以在一个系统中创建一个消息,然后订阅者在另一个系统中接收并处理这个消息。 4. 在同步时,可以通过判断数据库中的部门表的变化来确定需要同步的数据。可以使用增量同步的方式,即只同步新增或者修改的数据,而不同步已经删除的数据。可以在每次同步时记录上次同步的时间点,在下次同步时只同步在这个时间点之后发生变化的数据。 5. 在处理同步数据时,可以通过判断部门在目标系统是否存在来决定是新增、修改还是删除这个部门。如果目标系统中已经存在这个部门,则更新部门的相关属性;如果不存在这个部门,则新增这个部门;如果源系统中的部门已经被删除,则在目标系统中删除这个部门。 通过以上步骤,使用JAVA实现两个系统的部门同步功能就可以实现。可以根据实际需求和系统架构的不同进行适当的调整和优化。 ### 回答3: 要用JAVA实现两个系统的部门同步功能,可以按照以下步骤: 1. 连接两个系统:首先,需要建立两个系统之间的连接。可以使用JAVA提供的网络编程相关库来实现此功能,例如通过Socket建立一个TCP连接,或者使用HTTP协议进行通信。 2. 获取部门数据:在连接建立之后,需要从每个系统中获取部门的数据。可以使用系统提供的API或者数据库查询来获取数据。根据两个系统的数据结构和接口设计,使用JAVA编写代码来获取每个系统中的部门信息。 3. 数据同步:获取到两个系统中的部门数据之后,需要对数据进行同步操作。首先,需要比较两个系统中的部门数据是否一致,可以根据部门的唯一标识进行比较。如果两个系统中的部门数据不一致,就根据同步策略进行相应的操作,例如更新、插入或删除数据。 4. 实现同步功能:根据数据同步的逻辑和策略,在JAVA中编写代码来实现数据的同步操作。可以使用数据库操作语言来更新、插入或删除数据,或者使用系统提供的API来实现同步功能。 5. 异常处理:在进行数据同步操作时,可能会遇到一些异常情况,例如网络连接中断、数据格式错误等。为了保证系统的稳定性,需要在JAVA代码中添加异常处理机制,针对不同的异常情况进行相应的处理,例如进行重试、记录日志等。 总之,要用JAVA实现两个系统的部门同步功能,需要确保连接两个系统、获取数据、数据同步和异常处理等步骤都得到正确的实现。同时也要考虑代码的可读性和可维护性,使用合适的设计模式和编码规范,以便后续的代码维护和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值