利用IO流操作文件,如复制,删除等操作时,普通文件比较容易,但是如果涉及目录会相对而言容易出错,最近本人也做到了这方面的东西,所以就总结整理一下:对目录的操作,包括复制删除,最终的本质还是对普通文件的操作,所以递归的思想很有必要。
一、对整个目录的复制:
首先,写一个普通文件的复制方法
public static void copyFile(File src,File sdt)throws Exception{
/*try {
InputStream in = null;
OutputStream out = null;
try {
in = new BufferedInputStream(new FileInputStream(src),BUFFER_SIZE);
out = new BufferedOutputStream(new FileOutputStream(sdt),BUFFER_SIZE);
byte[] buffer = new byte[BUFFER_SIZE];
while (in.read(buffer) > 0){
out.write(buffer);
}
} finally {
if (null != in)
in.close();
if (null != out)
out.close();
}
} catch (Exception e) {
}*/
FileInputStream fi = null;
FileOutputStream fo = null;
FileChannel in = null;
FileChannel out = null;
try {
fi = new FileInputStream(src);
fo = new FileOutputStream(sdt);
in = fi.getChannel();//得到对应的文件通道-输入流
out = fo.getChannel();//得到对应的文件通道-输出流
in.transferTo(0, in.size(), out);//连接两个通道,并且从in通道读取,然后写入out通道
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fi.close();
in.close();
fo.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
被注释掉的部分,是利用缓冲字符流的原理逐行复制的,个人不太建议这种方式,因为操作的过程中发现当源文件有一个空白行时,复制出来的文件会出现NULNULNULNULNUL的字样,并且这种方式效率较低哦!
然后,开始用递归思想写一个复制目录的方法:
public static void copyDirectory(String srcDir, String desDir) {
try{
File des = new File(desDir);
if(!des.exists()) {
des.mkdirs();
}
File src = new File(srcDir);
File[] files = src.listFiles();
for(File file : files) {
//复制文件
if(file.isFile()) {
copyFile(file, new File(desDir + "\\" + file.getName()));
}else if(file.isDirectory()) {//复制文件夹,递归
copyDirectory(file.getAbsolutePath(), desDir + "\\" + file.getName());
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
二、删除目录(文件夹)
同理,也是利用递归的思想,不过,很容易出错:如果直接用file.delete()方法是行不通的,毕竟IO流还没有强大到直接删除整个目录的程度,delete方法只适合删除普通文件。
public static void deleteDir(File file) {
if(file.isFile()) {
file.delete();
}else if(file.isDirectory()) {
File[] list = file.listFiles();
for(File f : list) {
deleteFile(f);
}
}
file.delete(); //(1)
}
容易出错的地方就是(1)处,按照常理,遍历整个目录,子文件还是一个目录,直接用递归的思想删除不就得了,可是如果没有(1)处的代码,最后的结果将会是所有普通文件都被删除,但是会留下一堆空的文件夹!所以(1)处的代码最容易被遗漏。
三、补充:用Runtime(运行时)运行Linux命令时的注意事项
public static void executeCmd(String cmd){
try {
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
BufferedReader br =new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
} catch(Exception e) {
// log.debug(e.getMessage());
// log.error("ERROR#"+e.fillInStackTrace());
e.printStackTrace();
}
需要注意的是,调用这个工具方法会达到在Java程序中运行CMD命令的效果,不过需要注意的一些地方:
1)如果某一命令比如aapt.bat /apktool.bat等没有被加入环境变量中时,最好在命令中加上他们所在的路径,如:
String cmd = "F:\\aptool工具\\apktool\\apktool.bat b D:\\apk\\xxx.apk";
executeCmd(cmd);
如果加上了环境变量,就可以直接这样写:
String cmd = "apktool.bat b D:\\apk\\xxx.apk";
所以比较保险的做法是加上命令所在路径,因为不一定你就会专门去配环境变量!
2)命令要加后缀如.bat,否则会识别不了(cmd窗口中可以没有后缀,但是如果利用Runtime运行,最好加上),导致报错。
3)操作得到的结果会保存在Java程序所在项目的磁盘路径,而不是dos窗口里的前缀路径!