转载

基于Java 的增量与完全备份小工具

前段时间,因为各种原因,自己动手写了一个小的备份工具,用了一个星期,想想把它的设计思路放上来,当是笔记吧。

需求场景:这个工具起初的目的是为了解决朋友公司对其网络的限制(不可以用任何同步软件,git,外网SVN,U盘只读)。本来只是想做一个自动打包和发送邮件的工具,后来就发展成了这个。

软件功能:这个软件最终实现的功能包括1、读取配置文件,对配置文件中指定目录的文件进行日期检测,获取对应修改过的文件。2、将读出的文件进行压缩;3、将压缩文件发送到指定邮箱;4、对压缩文件进行历史版本的保留

根据最后的功能需求,工具最后选择采用的API包如下:

1、  使用commons-config实现配置文件的读写

2、  使用commons-io实现文件的检测和读写

3、  使用zip4j实现对文件的压缩

4、  使用javamail实现邮件的发送

系统最后的流程图如下:

基于Java 的增量与完全备份小工具

主要的工具类如下:

  1 //用于发送邮件的Bean   2 package com.sean.bean;   3    4 import java.io.File;   5 import java.io.IOException;   6 import java.io.InputStreamReader;   7 import java.io.UnsupportedEncodingException;   8 import java.util.Properties;   9   10 import javax.activation.DataHandler;  11 import javax.activation.FileDataSource;  12 import javax.mail.Address;  13 import javax.mail.BodyPart;  14 import javax.mail.Message;  15 import javax.mail.Message.RecipientType;  16 import javax.mail.MessagingException;  17 import javax.mail.NoSuchProviderException;  18 import javax.mail.Session;  19 import javax.mail.Transport;  20 import javax.mail.internet.AddressException;  21 import javax.mail.internet.InternetAddress;  22 import javax.mail.internet.MimeBodyPart;  23 import javax.mail.internet.MimeMessage;  24 import javax.mail.internet.MimeMultipart;  25 /**  26  * 邮件类  27  * @author Sean  28  * @blog http://www.cnblogs.com/Seanit/  29  * @email hxy9104@126.com  30  * 2015-6-9  31  */  32 public class EmailBean {  33     private Session session;  34     private MimeMessage message;  35     private Properties properties;  36     private MimeMultipart body;  37       38     /**  39      * 默认构造函数  40      */  41     public EmailBean(){  42     }  43       44       45     public EmailBean(Properties properties){  46         this.properties=properties;  47         createMail(properties);  48     }  49       50     public EmailBean(String src){  51         this.properties=new Properties();  52         try {  53             properties.load(new InputStreamReader(ClassLoader.getSystemResourceAsStream(src),"utf-8"));  54         } catch (UnsupportedEncodingException e) {  55             // TODO Auto-generated catch block  56             e.printStackTrace();  57         } catch (IOException e) {  58             // TODO Auto-generated catch block  59             e.printStackTrace();  60         }  61         createMail(properties);  62     }  63       64     /**  65      * 创建连接  66      * @author Sean  67      * 2015-6-8  68      * @param properties 邮箱相关配置  69      */  70     public  void createMail(Properties properties) {  71         this.properties=properties;  72         try {  73             session=Session.getDefaultInstance(properties,null);  74             message=new MimeMessage(session);  75             body=new MimeMultipart();  76         } catch (Exception e) {  77             e.printStackTrace();  78             throw new RuntimeException("邮件初始化失败");  79         }  80     }  81       82     /**  83      * 设置发件人  84      * @author Sean  85      * 2015-6-8  86      * @param from    发件人地址  87      * @return        成功返回true,失败防护false  88      */  89     public boolean setFrom(String from){  90         try {  91             message.setFrom(new InternetAddress(from));  92             return true;  93         } catch (Exception e) {  94             e.printStackTrace();  95             return false;  96         }   97     }  98       99     /** 100      * 设置收件人 101      * @author Sean 102      * 2015-6-8 103      * @param toSend    收件人邮箱地址 104      * @return            成功返回true,失败防护false 105      */ 106     public boolean setTOSend(String toSend){ 107         try { 108             message.setRecipients(RecipientType.TO, toSend); 109             return true; 110         } catch (MessagingException e) { 111             e.printStackTrace(); 112             return false; 113         } 114     } 115      116     /** 117      * 设置抄送人 118      * @author Sean 119      * 2015-6-8 120      * @param copyTo    抄送人地址 121      * @return            成功返回true,失败防护false 122      */ 123     public boolean setCopyTO(String copyTo){ 124         try { 125             message.setRecipients(RecipientType.CC, (Address[])InternetAddress.parse(copyTo)); 126             return true; 127         } catch (Exception e) { 128             e.printStackTrace(); 129             return false; 130         }  131     } 132      133      134     /** 135      * 设置主题 136      * @author Sean 137      * 2015-6-8 138      * @param subject    邮件主题 139      * @return            成功返回true,失败防护false 140      */ 141     public boolean setSubject(String subject){ 142         try { 143             message.setSubject(subject); 144             return true; 145         } catch (MessagingException e) { 146             e.printStackTrace(); 147             return false; 148         } 149     } 150      151     /** 152      * 设置邮件正文 153      * @author Sean 154      * 2015-6-8 155      * @param content    邮件正文 156      * @return            成功返回true,失败防护false 157      */ 158     public boolean setContent(String content){ 159         try { 160             BodyPart bodyPart=new MimeBodyPart(); 161             bodyPart.setContent(""+content, "text/html;charset=GBK"); 162             body.addBodyPart(bodyPart); 163             return true; 164         } catch (Exception e) { 165             e.printStackTrace(); 166             return false; 167         } 168     } 169      170     /** 171      * 添加附件 172      * @author Sean 173      * 2015-6-8 174      * @param src    附件地址 175      * @return 176      */ 177     public boolean addFiles(String src){ 178         try { 179             BodyPart bodyPart=new MimeBodyPart(); 180             FileDataSource file =new FileDataSource(src); 181             bodyPart.setDataHandler(new DataHandler(file)); 182             bodyPart.setFileName(file.getName()); 183             body.addBodyPart(bodyPart); 184             return true; 185         } catch (Exception e) { 186             e.printStackTrace(); 187             return false; 188         } 189     } 190      191     /** 192      * 发送邮件 193      * @author Sean 194      * 2015-6-8 195      * @return 196      */ 197     public boolean send(){ 198         Transport transport=null; 199         try { 200             message.setContent(body); 201             message.saveChanges(); 202             transport=session.getTransport(); 203             transport.connect(properties.getProperty("mail.smtp.host"), properties.getProperty("username"), properties.getProperty("password")); 204             transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO)); 205             if(message.getRecipients(Message.RecipientType.CC)!=null){ 206                 transport.sendMessage(message, message.getRecipients(Message.RecipientType.CC)); 207             } 208             return true; 209         } catch (Exception e) { 210             e.printStackTrace(); 211             return false; 212         }finally{ 213             try { 214                 transport.close(); 215             } catch (MessagingException e) { 216                 // TODO Auto-generated catch block 217                 e.printStackTrace(); 218             } 219         } 220     } 221 }
 1 //用于操作配置文件的bean  2 package com.sean.bean;  3   4 import org.apache.commons.configuration.ConfigurationException;  5 import org.apache.commons.configuration.PropertiesConfiguration;  6 /**  7  * 配置文件操作类  8  * 实现功能:对properties 文件进行读写操作  9  * @author Sean 10  * 2015-6-6 11  */ 12 public class PropertiesBean { 13     private String src=""; 14     private PropertiesConfiguration pc=null; 15     /** 16      * 默认构造函数 17      */ 18     public PropertiesBean() {} 19     public PropertiesBean(String src) { 20         this.src=src; 21         init(); 22     } 23      24     /** 25      * 初始化函数 26      * @author Sean 27      * 2015-6-6 28      */ 29     public void init(){ 30         if(src.trim().equals("")){ 31             throw new RuntimeException("The path is null"); 32         } 33         try { 34             pc=new PropertiesConfiguration(src); 35         } catch (ConfigurationException e) { 36             e.printStackTrace(); 37         } 38     } 39      40     /** 41      * 取值函数,根据对应的关键字获取对应的值 42      * @author Sean 43      * 2015-6-6 44      * @param key    关键字 45      * @return        返回关键字对应的值,若无该关键字,抛出异常 46      */ 47     public String getValue(String key){ 48         if(!pc.containsKey(key)){ 49             throw new RuntimeException("not such a key"); 50         } 51         return pc.getString(key); 52     } 53      54     /** 55      * 设置对应的值,传入键值对,根据关键字修改对应的值 56      * @author Sean 57      * 2015-6-6 58      * @param key    关键字 59      * @param value    值 60      */ 61     public void setValue(String key,String value){ 62         if(!pc.containsKey(key)){ 63             throw new RuntimeException("not such a key"); 64         } 65         pc.setProperty(key, value); 66         try { 67             pc.save(); 68         } catch (ConfigurationException e) { 69             // TODO Auto-generated catch block 70             e.printStackTrace(); 71         } 72     } 73      74     /** 75      * 设置配置文件的地址 76      * @author Sean 77      * 2015-6-6 78      * @param src    配置文件的路径 79      */ 80     public void setSrc(String src) { 81         this.src = src; 82     } 83 }
//用于进行IO操作的Bean package com.sean.bean; import java.io.File; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.commons.io.FileUtils; /**  * 文件操作工具类  * @author Sean  * @blog http://www.cnblogs.com/Seanit/  * @email hxy9104@126.com  * 2015-6-6  */ public class FilesBean {  private List<File> list=null;  public FilesBean(){}  /**   * 获取文件夹目录下的列表,目录为空返回空列表   * @param dir 传入对应文件夹目录   * @param ifFirst 控制递归时候的循环表示   * @return 返回list<File>文件列表   */  public  List<File> listFiles(String dir,boolean ifFirst){   /**    * 递归判断,仅在第一次调用函数的时候新建列表,为防止重复存入列表    */   if(ifFirst){    list=new ArrayList<File>();   }   if (dir==null||dir=="") {    return null;   }   for (File f : FileUtils.getFile(dir + "//").listFiles()) {    if (f.isDirectory()) {     listFiles(f.getAbsolutePath(),false);    } else {     list.add(f);    }   }   return list;  }  /**   * 根据过滤条件获取列表   * @param dir 目录   * @param filter 过滤条件   * @param ifFirst 递归标识   * @return   返回文件列表   */  public  List<File> listFiles(String dir,String filter,boolean ifFirst){   /**    * 递归判断,仅在第一次调用函数的时候新建列表,为防止重复存入列表    */   if(ifFirst){    list=new ArrayList<File>();   }   if (dir==null||dir=="") {    return null;   }   for (File f : FileUtils.getFile(dir + "//").listFiles()) {    if (f.isDirectory()) {     listFiles(f.getAbsolutePath(),filter,false);    } else {     if(!f.getName().endsWith(filter)){      list.add(f);     }    }   }   return list;  }  /**   * 获取指定目录下,指定日期修改后的文件   * @param dir 传入指定检测目录   * @param date 传入指定修改日期    * @param ifFirst 控制递归时候的循环表示   * @return  返回获取的文件列表,若目录或日期为空,则返回null   */  public  List<File> getModifiedFiles(String dir,Date date,boolean ifFirst){   /**    * 递归判断,仅在第一次调用函数的时候新建列表,为防止重复存入列表    */   if(ifFirst){    list=new ArrayList<File>();   }   if (dir==null||dir==""||date==null) {    return null;   }   for (File f : FileUtils.getFile(dir + "//").listFiles()) {    if (f.isDirectory()) {     getModifiedFiles(f.getAbsolutePath(),date,false);    } else {     if (FileUtils.isFileNewer(f, date.getTime())) {      list.add(f);     }    }   }   return list;  }  /**   * 获取某一日期之前创建的文件   * @author Sean   * 2015-6-9   * @param dir 文件路径     * @param ifFirst 控制递归时候的循环表示   * @param date 日期   * @return  返回列表   */  public  List<File> getOlderFiles(String dir,Date date,boolean ifFirst){   /**    * 递归判断,仅在第一次调用函数的时候新建列表,为防止重复存入列表    */   if(ifFirst){    list=new ArrayList<File>();   }   if (dir==null||dir==""||date==null) {    return null;   }   for (File f : FileUtils.getFile(dir + "//").listFiles()) {    if (f.isDirectory()) {     getOlderFiles(f.getAbsolutePath(),date,false);    } else {     if (FileUtils.isFileOlder(f, date)) {      list.add(f);     }    }   }   return list;  }  /**   * 获取除过滤条件外的修改文件列表   * @param dir   * @param date   * @param filter   * @param ifFirst   * @return   */  public  List<File> getModifiedFiles(String dir,Date date,String filter,boolean ifFirst){   /**    * 递归判断,仅在第一次调用函数的时候新建列表,为防止重复存入列表    */   if(ifFirst){    list=new ArrayList<File>();   }   if (dir==null||dir==""||date==null) {    return null;   }   for (File f : FileUtils.getFile(dir + "//").listFiles()) {    if (f.isDirectory()) {     getModifiedFiles(f.getAbsolutePath(),date,filter,false);    } else {     if (FileUtils.isFileNewer(f, date.getTime())) {      if(!f.getName().endsWith(filter)){       list.add(f);      }     }    }   }   return list;  } } 
//用于压缩文件的工具类 package com.sean.utils; import java.io.File; import java.util.ArrayList; import net.lingala.zip4j.core.ZipFile; import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.model.ZipParameters; import net.lingala.zip4j.util.Zip4jConstants; public class ZipUtil {  /**   * 压缩文件列表,无目录结构   * @author Sean   * 2015-6-6   * @param zipSrc zip文件地址   * @param list 文件列表   * @return  若成功,返回文件地址,不成功返回null   */  public static String zipFiles(String zipSrc,ArrayList<File> list){   ZipParameters zipParameters=new ZipParameters();   zipParameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);   zipParameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_MAXIMUM);   ZipFile zipFile=null;   try {    zipFile=new ZipFile(zipSrc);   } catch (ZipException e) {    // TODO Auto-generated catch block    e.printStackTrace();    return null;   }   try {    zipFile.addFiles(list, zipParameters);   } catch (ZipException e) {    // TODO Auto-generated catch block    e.printStackTrace();    return null;   }   return zipSrc;  }  /**   * 压缩文件夹   * @author Sean   * 2015-6-6   * @param src 文件夹地址   * @param zipSrc 压缩文件存放地址   * @return  若成功,返回文件夹地址,若不成功,返回null   */  public static String zipFolder(String src,String zipSrc){   ZipParameters zipParameters=new ZipParameters();   zipParameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);   zipParameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_MAXIMUM);   ZipFile zipFile=null;   try {    zipFile=new ZipFile(zipSrc);   } catch (ZipException e) {    // TODO Auto-generated catch block    e.printStackTrace();    return null;   }   try {    zipFile.addFolder(src, zipParameters);   } catch (ZipException e) {    // TODO Auto-generated catch block    e.printStackTrace();    return null;   }   return zipSrc;  }  /**   * 往zip文件中添加文件列表   * @author Sean   * 2015-6-7   * @param zipSrc zip文件路径   * @param list  要添加的文件列表   * @param src  要添加到zip文件中的哪个路径   */  public static void addFileToZip(String zipSrc,ArrayList<File> list,String src){   ZipFile zipFile=null;   try {    zipFile=new ZipFile(zipSrc);   } catch (ZipException e) {    // TODO Auto-generated catch block    e.printStackTrace();   }   ZipParameters zipParameters=new ZipParameters();   zipParameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);   zipParameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);   zipParameters.setRootFolderInZip(src);   try {    zipFile.addFiles(list, zipParameters);   } catch (ZipException e) {    // TODO Auto-generated catch block    e.printStackTrace();   }  }  /**   * 添加文件列表到zip根目录下   * @author Sean   * 2015-6-7   * @param zipSrc zip文件地址   * @param list  添加的文件列表   */  public static void addFileToZip(String zipSrc,ArrayList<File> list){   addFileToZip(zipSrc,list,"");  } } 
主流程: package com.sean.main; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import com.sean.bean.EmailBean; import com.sean.bean.FilesBean; import com.sean.bean.PropertiesBean; import com.sean.utils.ZipUtil; /**  * change2Mail 主程序  * 检测文件修改情况并发送给指定邮箱  * @version 1.0  * @author sean  * 2015-06-09  *  */ public class Change2Mail {  /**   * @param args   * @throws ParseException    */  public static void main(String[] args) throws ParseException{   //获取properties操作类   PropertiesBean propertiesBean = new PropertiesBean("cfg.properties");   FilesBean filesBean=new FilesBean();   //邮件对象   EmailBean email=new EmailBean("cfg.properties");   String first = propertiesBean.getValue("first");   //当前日期   String today=new SimpleDateFormat("yyyyMMdd").format(new Date());   //邮件正文   String content="";   //首次使用判断   if (first.trim().equals("true")) {    System.out.println("首次运行");    content+="欢迎首次使用change2Mail,<br/>以下是你的更改文件备份目录<br/>";    //获取检查文件目录    String cheakDir = propertiesBean.getValue("cheakDir");    if(!StringUtils.isEmpty(cheakDir)){     System.out.println("正在进行更改文件目录备份。。。。。。");     //目录分割     String[] dirs = cheakDir.split(";");     for (int i = 0; i < dirs.length; i++) {      File tmp=new File(dirs[i]);      List<File> list=filesBean.listFiles(dirs[i],true);      //创建对应文件存储目录列表      File file=new File(ClassLoader.getSystemResource("").getPath()+tmp.getName());      if(!file.exists()){       try {        file.createNewFile();       } catch (IOException e) {        // TODO Auto-generated catch block        e.printStackTrace();        System.out.println("创建目录列表记录文件失败。。。。。");        return ;       }       }      //将列表写入文件      logFiles(file,list);      //压缩文件并加入邮件      try {       ZipUtil.zipFolder(dirs[i], "tmp//"+tmp.getName()+today+".zip");       content+=tmp.getName()+"<br/>";       email.addFiles("tmp//"+tmp.getName()+today+".zip");      } catch (Exception e) {       e.printStackTrace();       System.out.println("压缩出错");       return ;      }     }    }    content+="以下是你的固定备份目录<br/>";    String zipDir = propertiesBean.getValue("zipDir");    if(!StringUtils.isEmpty(zipDir)){     System.out.println("正在进行固定备份目录备份。。。。。。");     String[] zipDirs = zipDir.split(";");     for (int i = 0; i < zipDirs.length; i++) {      try {       File tmp=new File(zipDirs[i]);       ZipUtil.zipFolder(zipDirs[i], "tmp//"+tmp.getName()+today+"bak.zip");       content+=tmp.getName()+"<br/>";       email.addFiles("tmp//"+tmp.getName()+today+"bak.zip");      } catch (Exception e) {       e.printStackTrace();       System.out.println("压缩出错");       return ;      }     }    }    System.out.println("更新配置文件。。。。。");    propertiesBean.setValue("first", "false");    propertiesBean.setValue("lastData", today);    System.out.println("发送文件。。。。。");    email.setFrom(propertiesBean.getValue("username"));    email.setTOSend(propertiesBean.getValue("toSend"));    email.setContent(content);    email.setSubject("change2Mail备份文件"+today);    if(email.send()){     System.out.println("发送成功");    }else{     System.out.println("发送失败");    }   } else {     System.out.println("备份开始。。。。。");     String data=propertiesBean.getValue("lastData");     String filter=propertiesBean.getValue("filter");     String cheakDir = propertiesBean.getValue("cheakDir");     content+="你好,自"+data+"起的文件变动如下:<br/>";     if(!StringUtils.isEmpty(cheakDir)){      System.out.println("正在进行更改文件目录备份。。。。。。");      String[] dirs = cheakDir.split(";");      for (int i = 0; i < dirs.length; i++) {       File tmp=new File(dirs[i]);       File file=new File(ClassLoader.getSystemResource("").getPath()+tmp.getName());       if(!file.exists()){        try {         file.createNewFile();        } catch (IOException e) {         System.out.println("创建文档失败");         e.printStackTrace();        }       }       content+="文件夹"+tmp.getName()+":<br/>";       List<File> list=filesBean.getModifiedFiles(dirs[i],new SimpleDateFormat("yyyyMMdd").parse(data),filter,true);       List<File> now =filesBean.listFiles(dirs[i],filter,true);       List<File> news=new ArrayList<File>();       List<File> del=new ArrayList<File>();       List<File> modefy=new ArrayList<File>();       List<String> lines=null;       try {        lines=FileUtils.readLines(file);       } catch (IOException e) {        e.printStackTrace();       }       System.out.println("检查新建和修改的文件。。。。。。");       for(File f:list){        if(!lines.contains(f.getAbsolutePath())){         news.add(f);        }else{         modefy.add(f);        }       }       System.out.println("检查删除的文件。。。。。。");       for(String f:lines){        File old=new File(f);        if(!now.contains(old)){         del.add(old);        }       }       logFiles(file,now);       content+="删除文件:<br/>";       for(File f:del){        content+=" "+f.getName()+"<br/>";       }       content+="新增文件:<br/>";       for(File f:news){        content+=" "+f.getName()+"<br/>";       }       content+="修改文件:<br/>";       for(File f:modefy){        content+=" "+f.getName()+"<br/>";       }       try {        if(list.size()!=0){         list.add(file);         ZipUtil.zipFiles("tmp//"+tmp.getName()+today+".zip", (ArrayList<File>)list);         email.addFiles("tmp//"+tmp.getName()+today+".zip");        }       } catch (Exception e) {        e.printStackTrace();        System.out.println("压缩失败");        return;       }      }      String zipDir = propertiesBean.getValue("zipDir");      if(!StringUtils.isEmpty(zipDir)){       System.out.println("正在进行固定备份目录备份。。。。。。");       String[] zipDirs = zipDir.split(";");       for (int i = 0; i < zipDirs.length; i++) {        try {         File tmp=new File(zipDirs[i]);         ZipUtil.zipFolder(zipDirs[i], "tmp//"+tmp.getName()+today+"bak.zip");         email.addFiles("tmp//"+tmp.getName()+today+"bak.zip");        } catch (Exception e) {         e.printStackTrace();         System.out.println("压缩出错");         return ;        }       }      }      System.out.println("更改配置文件。。。。。");      propertiesBean.setValue("lastData", today);      System.out.println("发送文件。。。。。");      email.setFrom(propertiesBean.getValue("username"));      email.setTOSend(propertiesBean.getValue("toSend"));      email.setContent(content);      email.setSubject("change2Mail备份文件"+today);      if(email.send()){       System.out.println("发送成功");      }else{       System.out.println("发送失败");      }      SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");       long to = df.parse(today).getTime();       long todel=Integer.parseInt(propertiesBean.getValue("time"))*(1000 * 60 * 60 * 24);       Date lastBak=new Date(to-todel) ;       System.out.println("删除"+df.format(lastBak)+"之前保存的历史文件。。。。。");       List<File> fileToDel=filesBean.getOlderFiles("tmp//", lastBak,true);       for(File f:fileToDel){        try {         FileUtils.deleteQuietly(f);       } catch (Exception e) {        // TODO: handle exception        e.printStackTrace();        System.out.println("删除"+f.getName()+"文件失败");       }       }      System.out.println(new Date());     }   }  }  /**   * 将文件列表的绝对地址输出到一个文件中   * @param file 输出文件   * @param list 文件列表   * @return  成功返回true,失败返回false   */  public static boolean logFiles(File file, List<File> list) {   List<String> lines=new ArrayList<String>();   try {     for (File f : list) {      lines.add(f.getAbsolutePath());     }     FileUtils.writeLines(file, lines,false);     return true;    } catch (IOException e) {     e.printStackTrace();     return false;    }  } } 
配置文件: #autho:sean  #data:2015/05/26 #email:hxy9104@126.com  #mail config  javamail的配置 mail.debug = true mail.smtp.auth = true mail.smtp.host = smtp.126.com mail.transport.protocol = smtp  #mail info 邮箱设置 username = 12121@126.com password = 121212 toSend = 121212@qq.com  #soft config 软件设置 #if the fisrt time to run  是否第一次运行 first = true #the path to check 检测的目录 cheakDir = F://myfolder//BaseClass; #the path allways to zip    完全备份的目录 zipDir = F://myfolder//myProject//Change2Mail; #the data lastcheck 最后备份时间 lastData = 20150629 #storage life of the bak zip 保留文件 time = 5 #filter string    过滤条件 filter = .class

工具github地址: https://github.com/Seanid/change2mail

为了便于使用,工具最后导出为jar包,并编写了一个bat进行执行,加入了jre文件夹,可以再无jdk环境下使用。最后压缩包地址: http://pan.baidu.com/s/1i3vQJv3

本工具只是个人闲时开发,纯属娱乐,大神勿喷

正文到此结束
Loading...