定时自动备份文件(java)

demo背景:由于同事说Excel表格在写着东西又突然被还原到之前的内容了,后面写的内容全部不见了。刚好最近自己在学习java,为此就用java写了一个小程序,这个小程序的功能比较简陋,纯属个人练习java某些语法点所用,具体如下:

1.可以指定需要备份的文件、和备份到哪个文件目录以及指定备份时间间隔;

2.只备份最新的文件,如果曾经已经存在过(也就是说文件被未知原因或人为恢复至前面的内容),则不备份,同时给予提示;

不足:

1.只能备份保存后的文件;

2.不支持大文件;

3.不支持备份目录;

4.不支持自动清理过期的备份文件;

实现原理:

1.通过生成文件的MD5值识别,并当做key添加进HashMap集合里面;

2.按一定时间段获取文件的MD5值,看是否改变,如果改变,并且HashMap里面的key没有相应的MD5值,则添加进集合。同时,把对应的文件备份。反之,不备份。

============================================================

1.获取文件MD5类(网上找的,出处暂时无从考证)

package md5offile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/**  * Md5校验工具类  * @author Fengwx  */  
public class MD5Util {
	public static void main(String[] args){
		System.out.println(getFileMD5(new File("D:/javaTest/c/c.txt")));
		System.out.println(getFileMD5(new File("D:/javaTest/a/b/c/abc")));
	}
	private static final char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9','a', 'b', 'c', 'd', 'e', 'f'};
	/**      * Get MD5 of a file (lower case) 
	* @return empty string if I/O error when get MD5
	*/
	public static String getFileMD5(File file) {            
		FileInputStream in = null;          
		try {              
			in = new FileInputStream(file);              
			FileChannel ch = in.getChannel();              
			return MD5(ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length()));          
			} catch (FileNotFoundException e) {              
				return "";          
				} catch (IOException e) {              
					return "";          
					} finally {              
						if (in != null) {                  
							try {                      
								in.close();                  
								} catch (IOException e) {                      
									// 关闭流产生的错误一般都可以忽略                 
									}              
							}          
						}        
		}        
	/**      * MD5校验字符串      * @param s String to be MD5
	 *       * @return 'null' if cannot get MessageDigest
	 *       */         
	private static String getStringMD5(String s) {
		MessageDigest mdInst;
		try {
			// 获得MD5摘要算法的 MessageDigest 对象             
			mdInst = MessageDigest.getInstance("MD5");
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
				return "";
				}
		byte[] btInput = s.getBytes();
		// 使用指定的字节更新摘要
		mdInst.update(btInput);
		// 获得密文
		byte[] md = mdInst.digest();
		// 把密文转换成十六进制的字符串形式
		int length = md.length;
		char str[] = new char[length * 2];
		int k = 0;
		for (byte b : md) {
			str[k++] = hexDigits[b >>> 4 & 0xf];
			str[k++] = hexDigits[b & 0xf];
			}
		return new String(str);
		}
	private static String getSubStr(String str, int subNu, char replace) {
		int length = str.length();
		if (length > subNu) {
			str = str.substring(length - subNu, length);
			} else if (length < subNu) {
				// NOTE: padding字符填充在字符串的右侧,和服务器的算法是一致的
				str += createPaddingString(subNu - length, replace);
				}
		return str;
		}
	private static String createPaddingString(int n, char pad) {
		if (n <= 0) {
			return "";
			}
		char[] paddingArray = new char[n];
		Arrays.fill(paddingArray, pad);
		return new String(paddingArray);
		}
	/**      
	 * * 计算MD5校验      
	 * * @param buffer      
	 * * @return 空串,如果无法获得 MessageDigest实例      
	 * */
	private static String MD5(ByteBuffer buffer) {
		String s = "";
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(buffer);
			byte tmp[] = md.digest();
			// MD5 的计算结果是一个 128 位的长整数,
			// 用字节表示就是 16 个字节
			char str[] = new char[16 * 2];
			// 每个字节用 16 进制表示的话,使用两个字符,
			// 所以表示成 16 进制需要 32 个字符
			int k = 0; 
			// 表示转换结果中对应的字符位置
			for (int i = 0; i < 16; i++) {
				// 从第一个字节开始,对 MD5 的每一个字节
				// 转换成 16 进制字符的转换
				byte byte0 = tmp[i];
				// 取第 i 个字节
				str[k++] = hexDigits[byte0 >>> 4 & 0xf];
				// 取字节中高 4 位的数字转换, >>>,
				// 逻辑右移,将符号位一起右移
				str[k++] = hexDigits[byte0 & 0xf];
				// 取字节中低 4 位的数字转换
				}
			s = new String(str);
			// 换后的结果转换为字符串
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
				}
		return s;
		}
		
}

 

2.实现备份类

package autoBackup;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Random;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;

import md5offile.*;

public class TimerBackupFile {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scan = new Scanner(System.in);
		System.out.println("输入需要备份的源文件:");
		String strPathSource = scan.nextLine();//输入需要备份的源目录。格式:D:\test.txt
		System.out.println("输入需要备份到哪里的目标目录:");
		String strPathTar = scan.nextLine();//输入需要备份到哪里的目标目录,必须存在的目录。格式:D:\javaTest\
		Timer t = new Timer();
		t.schedule(new BackupFile(strPathSource,strPathTar), 6000, 120000);//6秒后开始备份,每2分钟备份一次
		System.out.println("当前时间:" + BackupFile.setDateFormat(System.currentTimeMillis()));
		System.out.println("............");
	}
}

class BackupFile extends TimerTask{
	String strPathSource,strPathTar;
	HashMap<String,String> hm = new HashMap<>();
	
	public BackupFile(String strPathSource,String strPathTar){
		this.strPathSource = strPathSource;
		this.strPathTar = strPathTar;
	}
	
	public void backupFile(String strPathSource,String strPathTar){
		if(!hm.keySet().contains(BackupFile.getFileMD5(strPathSource))){//如果文件内容不变,或者恢复到之前的内容,都不备份。
			hm.put(BackupFile.getFileMD5(strPathSource), setDateFormat(System.currentTimeMillis()));//把文件的MD5值存入集合hm的key中
			try {
				BufferedInputStream bin = new BufferedInputStream(new FileInputStream(strPathSource));
				BufferedOutputStream bou = new BufferedOutputStream(
						new FileOutputStream(strPathTar + randomStr(10) + new File(strPathSource).getName()));//增加随机字符串,为的是防止文件名一样,备份失败
				int i = 0;
				while((i = bin.read())!=-1){
					bou.write(i);
				}
				bin.close();
				bou.close();
			} catch (FileNotFoundException e) {
				System.out.println("文件没有找到~!");
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(System.currentTimeMillis() + "文件备份成功!");
		}else{
			System.out.println("文件曾经存在过,不给予备份~请注意!");
		}
	}
	
	//生成随机数字符串
	public String randomStr(int len){
		Random rd = new Random();
		String temp = "";
		for(int i=0;i<=len;i++){
			int num = rd.nextInt(len);
			temp += String.valueOf(num);
		}
		return temp;
	}
	
	//转化时间格式
	public static String setDateFormat(long time){
		Date dt = new Date(time);
		DateFormat df = new SimpleDateFormat("YYYY年MM月DD日 hh时MM分ss秒");
		return df.format(dt);
	}
	
	//生成文件的MD5值
	public static String getFileMD5(String strPathSource){
		return MD5Util.getFileMD5(new File(strPathSource));
	}
	
	public void run(){
		backupFile(strPathSource,strPathTar);
	}
}

 

 

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/bysu/blog/827632

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值