同步方向:源文件夹--->目标文件夹
改进版: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();
}
});
}
}
运行截图