先说一下功能概要:
将文件或文件夹以关键字开头的名字复制到另一个目录下。
附加功能:定时检测源目录是否有新增文件或文件夹,并实时拷贝。
//拷贝文件/夹的方法
public class CopyFolder {
//是否是目标关键字文件夹
private static boolean IS_AIM_FOLDER = false;
/**
* 分析:
* A:封装数据源File
* B:封装数据目的地File
* C:判断该File是文件夹还是文件
* a:是文件夹
* 就在目的地目录创建该文件夹
* 获取该File对象下的所有文件或者文件夹File对象 遍历得到每一个File对象
* 回到C
* b:是文件
* 直接复制
*
*/
public static void main(String[] args) throws IOException {
// 源路径
File srcFile = new File("Z:\\AA\\A\\B\\C");
// 目标路径
File destFile = new File("Z:\\BB\\A\\B\\C");
// 调用方法
copyFolder(srcFile, destFile,destFile);
}
/**
* 递归复制文件夹
* @param srcFile
* @param destFile
* @param aimFile 仅提供对比
* @throws IOException
*/
public static void copyFolder(File srcFile, File destFile,File aimFile) throws IOException {
// 1.判断File对象是否是文件夹
if (srcFile.isDirectory()) {
//2.判断文件夹名称是否包含关键字
if(srcFile.getName().startsWith("运营发送")|| IS_AIM_FOLDER){
IS_AIM_FOLDER = true;
//3.包含则复制当前文件夹的所有文件
// 拼接新文件夹所在路径
File newFolder = new File(destFile, srcFile.getName());
// 创建文件夹
newFolder.mkdir();
// 遍历源路径下的所有File对象
File[] fileArray = srcFile.listFiles();
for (File file : fileArray) {
// 递归调用
copyFolder(file, newFolder, aimFile);
}
IS_AIM_FOLDER = false;
}else{
//4.不包含则向下遍历
// 遍历源路径下的所有File对象
File[] fileArray = srcFile.listFiles();
for (File file : fileArray) {
// 递归调用
copyFolder(file, destFile,aimFile);
}
}
} else {
//5.判断是否属于关键字目录下的、是否包含关键字、是否还在当前文件夹的循环条件内、目标文件夹是否有改变。含任何一种条件都可复制
if(srcFile.getName().startsWith("运营发送")||destFile.getName().startsWith("运营发送")
|| IS_AIM_FOLDER ||!aimFile.equals(destFile) ){
// 拼接新文件所在路径
File newFile = new File(destFile, srcFile.getName());
// 调用方法,复制文件
copyFile(srcFile, newFile);
}
}
}
// 高效字节流一次读取一个字节数组复制文件
public static void copyFile(File srcFile, File newFile) throws IOException, FileNotFoundException {
// 数据源
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcFile));
// 目的位置
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(newFile));
// 定义单次读取字节数组的大小,一般就写1024
byte[] bys = new byte[1024];
// read(byte[] bys)方法返回值为获取到的字节个数,若没有获取到,则返回-1
int length = 0;
while ((length = bis.read(bys)) != -1) {
// write(byte[] bys,int off,int length)方法指的是从指定字节数组的指定位置开始写入(复制到)文件
bos.write(bys, 0, length);
}
// 关闭输出流
bos.close();
// 关闭输入流
bis.close();
}
}
下面调用方法不能直接调上面的,需要将上面这段拷贝的代码main方法改成普通方法,然后将类注入,在下面定时检测时调用即可。
注意:下面的copyFolder.copyFunc(filePath,destFile)是调用的
//定时检测方法
private static String srcFile = "Z:\\AA\\A\\B\\C";
private static String destFile = "Z:\\BB\\A\\B\\C";
//启动项目自动执行
@PostConstruct
public String getFile() throws FileNotFoundException, IOException {
final Timer timer = new Timer();
String fileName1="";
timer.schedule(new TimerTask() {
public void run() {
WatchKey key;
try {
WatchService watchService = FileSystems.getDefault().newWatchService();
Paths.get(srcFile).register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
while (true) {
File file = new File(srcFile);//path为监听文件夹
File[] files = file.listFiles();
key = watchService.take();//没有文件增加时,阻塞在这里
for (WatchEvent<?> event : key.pollEvents()) {
//获取到刚传的文件路径
String filePath = srcFile + "\\" + event.context();
// if (fileName.startsWith("运营发送")){
// Thread.sleep(1000);//休眠一秒
copyFolder.copyFunc(filePath,destFile);
// }
}
if (!key.reset()) {
break; //中断循环
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 2000, 3000);//第一个数字2000表示,2000ms以后开启定时器,第二个数字3000,表示3000ms后运行一次run
return "";
}
以上代码亲测可用。