文件复制的疑惑

最近在写一个gradle插件过程中,为Task定义文件复制方法时,发现文件并没有被复制,本来是一个很简单的操作,却出现了如此不解的现象。因编写gradle插件调试不易,所以花了比较多的时间才发现问题,所以谨此记录。

下面一个精简版的Task类:

import java.io.File;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.apache.commons.io.FileUtils;
import org.gradle.api.tasks.TaskAction;

public class MyTask {
	private List<Action> actions = new CopyOnWriteArrayList<>();

	public void copy(final String source, final String dest) throws Exception {
		this.actions.add(new Action() {
			@Override
			public void execute() throws Exception {
				FileUtils.copyFile(new File(source), new File(dest));
			}
		});
	}

	public void copyDependencies() {
		this.actions.add(new Action() {
			@Override
			public void execute() throws Exception {
				File dir = new File("H:\\sourceDir");//测试代码源目录
				for(File file : dir.listFiles()) {
					copy(file.getAbsolutePath(), "H:\\destDir\\"+file.getName());
				}
			}
		});
	}

	@TaskAction
	public void execute() throws Exception {
		for(Action action : this.actions) {
			action.execute();
		}
	}

	public static interface Action {
		void execute() throws Exception;
	}

}

如上代码中,为了统一各个方法调用,调用方法时只是在actions列表中添加一个Action,在真正执行Task时迭代actions,依次执行各个Action。在MyTask的构建脚本中会调用copy与copyDependencies方法。如果List使用的是ArrayList而不是CopyOnWriteArrayList的话,执行过程中将会抛出ConcurrentModificationException异常,因为ArrayList在迭代的过程不允许对其进行修改(增加或移除元素)。但是即使使用了ConcurrentModificationException后也并没有达到预期目的,即进行文件复制。细看代码后发现,虽然CopyOnWriteArrayList支持迭代过程对列表进行修改,但是copyDependencies方法中调用copy方法其本意是为了复用copy方法,而这其实只是向actions列表中添加了一个新的Action而已,并不是在执行Action,所以copyDependencies方法中的“文件复制”功能无效。

明白问题原因为后改进MyTask类为:

import java.io.File;
import java.util.List;
import java.util.ArrayList;

import org.apache.commons.io.FileUtils;
import org.gradle.api.tasks.TaskAction;

public class MyTask {
	private List<Action> actions = new ArrayList<>();

	public void copy(final String source, final String dest) throws Exception {
		this.actions.add(new Action() {
			@Override
			public void execute() throws Exception {
				FileUtils.copyFile(new File(source), new File(dest));
			}
		});
	}

	public void copyDependencies() {
		this.actions.add(new Action() {
			@Override
			public void execute() throws Exception {
				File dir = new File("H:\\sourceDir");
				for(File file : dir.listFiles()) {
					//不再调用copy方法,而是直接进行文件复制,这样就避免了仅向actions列表中添加元素
					//列表类型也可以使用ArrayList了
					FileUtils.copyFile(file, new File("H:\\destDir\\"+file.getName()));
				}
			}
		});
	}

	@TaskAction
	public void execute() throws Exception {
		for(Action action : this.actions) {
			action.execute();
		}
	}

	public static interface Action {
		void execute() throws Exception;
	}

}
时间: 2024-12-18 11:44:40

文件复制的疑惑的相关文章

Linux 将文件夹下的所有文件复制到另一个文件里

如何将文件夹/home/work下的文件复制到/home/temp里面? 使用命令: cp -R /home/work/* /home/temp *表示所有文件 但是/home/work 下的隐藏文件都不会被拷贝 更好的复制的方法是用"."代替"*"就好了. cp -R /home/work/.  /home/temp 将一个文件夹复制到另一个文件夹下,例如将/home下的work文件夹复制到temp下面 命令为: cp -R /home/work  /home/t

将本地文件复制到复制到Hadoop文件系统

//将本地文件复制到复制到Hadoop文件系统 //目前,其他Hadoop文件系统写入文件时均不调用progress()方法. package com; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import org.apache.hadoop.co

文件复制和备份

net use h: \\192.168.50.3\pub "123456" /user:"administrator" 或先登录共享文件夹 xcopy 源文件夹 目的文件夹 /O /X /E /H /K robocopy 源文件夹 目的文件夹 /mir /e /copyall  (大文件推荐) robocopy还提供了很多xcopy不具备的功能: 可选择多种文件类型复制到目标文件夹 可指定在复制时不复制的文件类型 可指定复制目录的级次,如只复制两级目录 可按文件的

Win7 自带FTP将文件复制到FTP服务器时发生错误。

错误截图: 错误信息: 将文件复制到FTP服务器时发生错误.请检查是否有权限将文件放到该服务器上. 详细信息: 200 Type set to I. 200 PORT commad successful. 451 No mapping for the Unicode character exits in target multi-bye code page. 解决方案: 控制面板-->管理工具-->打开Internet信息服务(IIS)管理器.右键选中自己建立好的FTP站点,选择"管

VS发布 错误 未能将文件 复制到

自己一手搭建的网站 ASP.MVC4 最近修改写功能 之后一直发布不了 一直报 错误 15 未能将文件 easyui\themes\gray\images\Thumbs.db 复制到 obj\Release\Package\PackageTmp\easyui\themes\gray\images\Thumbs.db. 未能找到文件"easyui\themes\gray\images\Thumbs.db". 0 0 MvcTender 错误 14 未能将文件 easyui\themes\

用fread和fwrite实现文件复制操作

#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc,char **argv) { FILE *fp_src,*fp_des; char buf[128]; int num; if(argc!=3) { printf("the format must be: cp_example file_src file_des\n"); exit(EXIT_FAI

JavaIO(06)文件复制

文件复制一般是采用两种方式进行操作: 1:将源文件中的内容全部读取到内存中,并一次性的写入到目标文件中:(不常用这种方式) 2:不将源文件中的内容全部读取进来,而是采用边读边写的方式: 实例01: package cn.itcast05; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; //一次一个字节复制 //一次一个字节数组复制 public class

文件复制二进制版

两种复制方式: FILE *src = fopen("src.txt","r"); FILE *dest = fopen("dest.txt","w"); Char buf[1024]={0}; While(!feof(src)){ Size_t size = fread(buf,1,sizeof(buf),src); Fwrite(buf,1,size,dest); } 采用 stat函数 #include <sys/

将u盘的文件复制到虚拟机上的linux系统上面—》文件挂载(文字+图解)

虚拟机中操作系统.CentOs(无图形界面) 没有图形界面的linux,我也没有配置网络,现在需要把文件复制到linux系统上面,我这里就使用了u盘挂载的方式,获得了U盘中的文件. 1.VMware中设置USB的属性 编辑虚拟中系统信息 USB的三个信息必须全部勾选 2.开启VMware的USB服务 记得查看一下是否开启改USB服务(没注意,坑了好久才查找原因),我的电脑右键->管理->服务和应用程序 ->VMware USB Arbitration Service右键->开启服务