参考文档地址:
http://yearsaaaa123789.iteye.com/blog/1404865
我是在写一段用java执行文件夹拷贝的时候遇到的这个问题,一开始想的是用递归copy的方式去做,代码如下:
//copy文件夹
public static boolean copyDirectory(String sourcePath,String targetPath) throws Exception{
boolean flag = true;
File soureFolder = new File(sourcePath);
File targetFolder = new File(targetPath);
//源文件不存在或者不是文件夹,则返回false
if(!soureFolder.exists() || !soureFolder.isDirectory())
return false;
//目标文件夹存在时,先删除再重建
if(!targetFolder.exists())
createFile(targetFolder.getAbsolutePath());
else{
deleteDirectory(targetFolder.getAbsolutePath());
createFile(targetFolder.getAbsolutePath());
}
File[] files = soureFolder.listFiles();
for (int i = 0; i < files.length; i++) {
//copy子文件
if (files[i].isFile()) {
flag=copyFile(soureFolder.getAbsolutePath() + "\\" +files[i].getName(),targetFolder.getAbsolutePath() + "\\" +files[i].getName());
if (!flag){
System.out.println("copy失败,copy文件名称:" + soureFolder.getAbsolutePath()+"\\" +files[i].getName());
break;
}
} //copy子目录
else {
flag=copyDirectory(soureFolder.getAbsolutePath() + "\\" +files[i].getName(),targetFolder.getAbsolutePath() + "\\" +files[i].getName());
if (!flag){
System.out.println("copy失败,copy文件夹名称:" + soureFolder.getAbsolutePath()+"\\" +files[i].getName());
break;
}
}
}
if (!flag)
return false;
else
return flag;
}
但这种方式copy速度实在太慢,600M的东西要拷贝400秒,在网上看到别人的一段评语,copy文件夹为什么不用windows命令呢,他认为这是最快的一种文件夹copy方式;因此我自己也去尝试了一下,速度确实快,600M的东西,只要75秒左右就OK,代码如下:
//执行window cmd命令
public static ArrayList<String> runWinCommond(String winCommond)
{
ArrayList<String> arraylist = new ArrayList<String>();
try
{
Process process =Runtime.getRuntime().exec("cmd /c " + winCommond);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
//while((s=bufferedReader.readLine()) != null);
for (String res = ""; (res = bufferedReader.readLine()) != null;)
{
arraylist.add(res);
}
process.waitFor();
bufferedReader.close();
//Thread.currentThread().sleep(1000);
} catch (Exception e)
{
e.printStackTrace();
}
return arraylist;
}
一开始代码中并没有bufferedReader.readLine()和process.waitFor()这些代码,我以为Runtime.getRuntime().exec()在执行过程中会等到windows命令执行结束后才会返回,但结果是,异步处理,直接返回,因此我在这里需要有一个等待方法,我在网上搜到了waitFor()这个方法,跟原文中类似,在使用过程中因为没有bufferedReader.readLine()这样的方法来读取缓存中的数据,造成程序阻塞在waitfor()这里,当然根据原文,加上这样的读取操作,就OK了;
另外,原文中有一段文字,Mark一下:
看看waitFor()的说明:
JDK帮助文档上这么说:如有必要,一直要等到由该 Process 对象表示的进程已经终止。如果已终止该子进程,此方法立即返回。但是直接调用这个方法会导致当前线程阻塞,直到退出子进程。对此JDK文档上还有如此解释:因为本地的系统对标准输入和输出所提供的缓冲池有效,所以错误的对标准输出快速的写入何从标准输入快速的读入都有可能造成子进程的所,甚至死锁。
最后:
对于像文件夹copy这种操作,window是会起一个xcopy.exe的进程(我用的是xcopy命令)来完成这个copy动作,copy完成以后该进程终止,对于这种操作,用上面的方法是没有问题的,即加waitFor进行等待,但对于像用java发送windows命令来启动一个程序这种操作,就不能加waitfor这样的语句了,首先,启动一个程序,一般不会有输出信息被返回,因此,waitFor不存在阻塞的情况,这里如果使用waitFor方法,该语句就会等到你启动的那个程序被关闭后,waitfor才会返回,而之前,程序就会阻塞在waitFor这条语句这里,这种情况,显然是我们所不希望的;
鉴于上面的情况,我一般会写两个window命令执行方法,一个用于执行即时命令,命令执行后,立即返回(不加waitFor语句),另外一个就是执行延迟性命令(加waitFor),这种就是处理像文件copy这种延迟性的;