package free;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
public class MainFrame extends JFrame {
private final int WIDTH=600;
private final int HEIGHT=400;
protected JButton b1;
protected JButton b2;
protected JButton syn;
protected JTextField jtf1;
protected JTextField jtf2;
protected JTextArea area;
protected JMenuBar mbar;
private java.util.List<File> from=new LinkedList<File>();
private java.util.List<File> to=new LinkedList<File>();
public MainFrame(){
this.setSize(WIDTH, HEIGHT);
/*创建菜单
* */
mbar=new JMenuBar();
this.setJMenuBar(mbar);
this.setTitle("DirSyn");
JMenu menu=new JMenu("File");
JMenuItem jmi1=new JMenuItem("Open source");
JMenuItem jmi2=new JMenuItem("Open destination");
JMenuItem jmi3=new JMenuItem("Exit");
menu.add(jmi1);
menu.add(jmi2);
menu.addSeparator();
menu.add(jmi3);
mbar.add(menu);
/*初始化其他控件,并添加监听器
* */
b1=new JButton("Open source");
b2=new JButton("Open destination");
syn=new JButton("Synchronize");
jtf1=new JTextField(20);
jtf2=new JTextField(20);
//将 area 封装在滚动条内
area =new JTextArea(10,40);
JScrollPane sbar=new JScrollPane();
sbar.setViewportView(area);
sbar.setAutoscrolls(true);
sbar.setEnabled(true);
//设置布局
JPanel bottom = new JPanel();
GridBagLayout gridBagLayout = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
c.fill=GridBagConstraints.HORIZONTAL;
bottom.setLayout(gridBagLayout);
//bottom.setBackground(Color.GRAY);
bottom.setAlignmentX(LEFT_ALIGNMENT);
bottom.setAlignmentY(TOP_ALIGNMENT);
gridBagLayout.setConstraints(b1, c);
bottom.add(b1);
c.gridwidth=GridBagConstraints.REMAINDER;
gridBagLayout.setConstraints(jtf1, c);
bottom.add(jtf1);
c.gridwidth=1;
c.gridy=1;
gridBagLayout.setConstraints(b2, c);
bottom.add(b2);
gridBagLayout.setConstraints(jtf2, c);
bottom.add(jtf2);
c.gridy=2;
gridBagLayout.setConstraints(syn, c);
bottom.add(syn);
c.gridy=3;
c.gridwidth=GridBagConstraints.REMAINDER;
c.gridheight=4;
JPanel dt=new JPanel();
dt.setBorder(new TitledBorder("Detail"));
dt.add(sbar);
gridBagLayout.setConstraints(dt, c);
bottom.add(dt);
getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));
getContentPane().add(bottom);
//设置监听器
b1.addActionListener(new addFileListener());
b2.addActionListener(new addFileListener());
syn.addActionListener(new addFileListener());
/*设置窗体位置*/
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension d=Toolkit.getDefaultToolkit().getScreenSize();
this.setLocation(((int)d.getWidth()-WIDTH)/2 ,((int)d.getHeight()-HEIGHT)/2 );
this.setVisible(true);
}
class addFileListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent arg0) {
if(arg0.getActionCommand().equals("Open source")){
System.out.println("source clicked");
JFileChooser jfc=new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
jfc.showOpenDialog(MainFrame.this);
File file=jfc.getSelectedFile();
if(file==null)return;
jtf1.setText(file.getAbsolutePath());
//将选择文件下的 所有文件 压入 堆栈
pushFile(file,from);
}else if(arg0.getActionCommand().equals("Open destination")){
System.out.println("destination clicked");
JFileChooser jfc=new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
jfc.showOpenDialog(MainFrame.this);
File file=jfc.getSelectedFile();
if(file==null)return;
jtf2.setText(file.getAbsolutePath());
//将选择文件下的 所有文件 压入 堆栈
pushFile(file,to);
}else if(arg0.getActionCommand().equals("Synchronize")){
System.out.println("synchronized clicked");
if(jtf1.getText()==null || jtf2.getText()==null ||jtf1.getText().trim().length()<=0||jtf2.getText().trim().length()<=0){
JOptionPane.showMessageDialog(MainFrame.this, "请选择两个需要同步的文件夹");
return ;
}
if(synDir(from ,to)){
JOptionPane.showMessageDialog(MainFrame.this, "同步成功", null,JOptionPane.INFORMATION_MESSAGE);
}else{
JOptionPane.showMessageDialog(MainFrame.this, "同步失败", null, ERROR);
}
}
}
//将 已选文件夹中 所有类型 文件 压入 对应 堆栈,等待 同步处理
public void pushFile(File dir,java.util.List<File> ls){
if(dir==null)return;
String dirPath=dir.getAbsolutePath();
String[] fn=dir.list();
for(String f:fn){
File fi=new File(dirPath+"/"+f);
if(fi.isFile()){
ls.add(fi);
System.out.println(fi.getAbsolutePath());
}else{
pushFile(fi,ls);
}
}
}
//同步时,以源文件夹 为据,依次同步最新文件。同步完成后,目的文件夹中剩余的 文件将复制到源文件夹
public boolean synDir(java.util.List<File> dfrom,java.util.List<File> dto){
if(dfrom.size()<=0 && dto.size()<=0){
JOptionPane.showMessageDialog(MainFrame.this, "需要同步的两个文件夹都是空的");
return false;
}
for(File f:from){
String str=f.getAbsolutePath().replace(jtf1.getText().trim(), jtf2.getText().trim());
//组建一个临时文件(用目标文件夹路径 替换 源文件夹路径),便于从目标文件中 查找与此一致的文件
File tempFile =new File(str);
//No1.如果存在源文件夹中的 文件 也存在目标文件夹,
if(dto.contains(tempFile) ){
synFile(f, dto.get(dto.indexOf(tempFile)));
//同步完后 ,从目标文件夹 堆栈 删除 改文件
dto.remove(tempFile);
}else{ //No2.否则,文件存在源文件夹,不存在于目标文件夹
String str2=f.getAbsolutePath().replace(jtf1.getText().trim(), jtf2.getText().trim());
synFile(f,new File(str2));
}
}
//No3.存在于目标文件夹,但是不存在于源文件夹
if(dto.size()>0){
for(File f:dto){
String str=f.getAbsolutePath().replace(jtf2.getText().trim(), jtf1.getText().trim());
synFile(f,new File(str));
}
}
return true;
}
//根据文件 最后依次修改时间,确定最新文件,然后同步
public void synFile(File dfile,File tfile){
if(dfile.lastModified()>tfile.lastModified()){
area.append("Synchronized from "+dfile.getAbsolutePath()+" to " +tfile.getAbsolutePath()+"/n");
copyFile(dfile,tfile);
}else if(dfile.lastModified()<tfile.lastModified()){
area.append("Synchronized from "+tfile.getAbsolutePath()+" to " +dfile.getAbsolutePath()+"/n");
copyFile(tfile,dfile);
}
}
//复制文件
public boolean copyFile(File fromf,File tof){
FileInputStream in=null;
FileOutputStream out=null;
byte[]buffer=new byte[4*1024];
try {
//如果目标文件不存在
if(!tof.exists()){
//创建路径
File d=tof.getParentFile();
d.mkdirs();
//创建文件
boolean r=tof.createNewFile();
area.append("New file "+tof.getAbsolutePath()+"/n");
}
in=new FileInputStream(fromf);
out=new FileOutputStream(tof);
while( (in.read(buffer) )>0 ){
out.write(buffer);
}
out.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(in!=null)in.close();
if(out!=null)out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
}
}