昨天室友电话面试阿里内推的时候问到了Java里面的File有关目录和文件遍历的问题,之前做项目的时候用到过,不过时间长了都忘了。File类作为Java IO的一个工具类在面试中碰到的概率很高,因此做一下总结。
File类这个名字具有一定的误导性,我们可能会认为它指代的是文件,实际上却并非如此。它既能代表一个特定文件的名字,又能代表一个目录下的一组文件的名称。
新建文件的时候要注意一点,’\’在Java中是转义字符在Java中遇到’\’要使用’\\’或者’/’来代替,因此可以使用下面两种方式来新建一个文件。如果传入的pathname的值为null则回抛出空指针异常。
/*
*文件路径为:D:\JAVAworkspace\ProgramTest\src\泛型\Canvas.java
**/
//1
File file = new File("D:\\JAVAworkspace\\ProgramTest\\src\\泛型\\Canvas.java");
//2
File file = new File("D:/JAVAworkspace/ProgramTest/src/泛型/Canvas.java");
注意File(String pathname)中的pathname必须是一个已经存在的文件路径名,如果文件路径名不存在则会创建失败。
用于判断文件是否存在如果存在则返回true反之返回false。
File file=new File("D:/a.txt");
System.out.println(file.exists());
/*如果d盘目录下并不存在a.txt文件则会输出false,反之输出true*/
如果文件不存在就会创建一个新文件,和File(String pathname)不同的是,File()并不会在系统的硬盘中中创建一个并不存在的文件,而creatNewFile()会创建一个并不存在的文件也就是创建一个新文件。
如果系统中已经有了pathname路径的文件,则creatNewFile()创建文件失败会返回false,反之会返回true。
/*刚开始是d盘中并无a.txt文件。*/
File file=new File("D:/a.txt");
System.out.println(file.exists());//输出false
System.out.println(file.createNewFile());//创建成功输出true
/*----------------------------------------------------- */
System.out.println(file.exists());/*由于调用createNewFile()方法后会在d盘下创建a.txt文件所以此时输出true。*/
System.out.println(file.createNewFile());//由于a.txt文件已经存在所以输出false
由上面可知creatNewFile()和File()方法的区别,File()方法只是将磁盘中的某个已存在的文件导入到Java应用中,而creatNewFile()则是在磁盘中创建一个新文件。
mkdir()用于创建目录,要注意的是mkdir()只在给定的目录下创建子目录,如果给定的目录并不存在那么就会创建失败。
File file=new File("D:/hanking/mkdir");
System.out.println(file.mkdir());
//如果d盘中不存在hanking目录则输出false,反之输出true并在hanking目录下创建mkdir目录
上面代码在D:/hanking下创建mkdir目录,如果D:/hanking并不存在那么创建失败file.mkdir()返回false。如果D:/hanking已经存在则会在D:/hanking下创建mkdir目录并且file.mkdir()返回true。
与mkdir()方法不同,mkdirs()如果给定路径中的目录不存在则将路径中的所有目录一起创建,创建成功返回true否则返回false。
File file=new File("D:/hanking/mkdirs");
System.out.println(file.mkdirs());//输出true
//hanking目录并不存在,但是调用mkdirs()方法后,将hanking目录与mkdirs目录一起创建了。
renameTo()方法用于文件或者文件夹重命名。并且可以将一个文件移动到另一个文件夹中。
/*给文件夹重命名*/
File file=new File("D:/hanking/mkdir");
boolean suc=file.renameTo(new File("D:/hanking/mkdirs"));
/*
将文件夹重命名后移动到另一个文件夹
*/
File file=new File("D:/hanking/mkdir");
boolean suc=file.renameTo(new File("D:/hust/mkdirs"));
用于删除文件或目录,如果删除成功则返回true否则返回false,返回false的原因有很多,文件被打开,或者文件权限等情况都会返回false。
/*删除d中的hanking目录*/
File file=new File("D:/hanking");
System.out.println(file.delete());
检查file是否是目录如果是返回true否则返回false。
File file = new File("c:\\data");
boolean isDirectory = file.isDirectory();
list() 和 listFiles()方法是两个特别重要的方法,在面试的时候经常会问到。list()方法会返回给定目录下所有的子目录名字的字符串以及所有目录中的文件名字字符串。listFiles()方法会返回给定目录下所有的子目录串以及所有目录中的文件。注意到list()和listFiles()的不同之处在于一个是返回字符串数组,一个是返回File数组。
list()实例
运行代码之前在run configure中的 Arguments中输入”A.*\.java”
package files;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Arrays;
import java.util.regex.Pattern;
public class DirList {
public static void main(String[] args) throws IOException {
File path=new File("D:/JAVAworkspace/ProgramTest/src");
String []list;
if(args.length==0)
list=path.list();
else {
list=path.list(new DirFilter(args[0]));
}
Arrays.sort(list,String.CASE_INSENSITIVE_ORDER);
for(String dirItem:list)
System.out.println(dirItem);
}
}
class DirFilter implements FilenameFilter
{
private Pattern Pattern;
public DirFilter(String regex) {
Pattern =java.util.regex.Pattern.compile(regex);
}
@Override
public boolean accept(File dir, String name) {
return Pattern.matcher(name).matches();
}
}
/*输出
AcSort.java
Add.java
ApproximateFloat.java
ArrayListDemo.java
ArrayListTest.java
Autoboxing.java
*/
上面的这段代码用于过滤出给定目录下所有以A开头以.java结尾的文件并且结果按字符串的升序排列。实现FilenameFilter接口就可以过滤出自己想要的文件。
遍历目录是面试中的常见题目,并且遍历目录在实际运用中也会经常遇到,在遍历目录之前先看看目录的结果如下图。图中黄色的矩形代表目录,圆形代表各种后缀的文件。
由图可知目录结构是一棵树。因此遍历目录可以使用树的遍历方式来进行。图中的目录结构是一棵子集树,那么用回溯法就可以很容易的进行遍历。
方法1(回溯法)
package files;
import java.io.File;
public class FileTraverse {
public static void main(String[] args) {
traverse(new File("D:/qq"));
}
// 回溯法
private static void traverse(File file) {
File flist[] = file.listFiles();
if (flist == null || flist.length == 0) {
return;
}
for (File f : flist) {
if (f.isDirectory()) {
//输出文件夹名字
System.out.println("Dir: " + f.getName());
//递归的遍历文件夹
traverse(f);
} else {
//输出文件名字
System.out.println("file: " + f.getName());
}
}
}
}
方法2广度优先遍历
//广度优先遍历,使用队列
private static void traverseBSP(File file) {
Queue queue=new LinkedList();
if(file!=null)
{
queue.add(file);
}
while(!queue.isEmpty())
{
//输出文件名或者目录名
System.out.println(queue.peek().getName());
File []flist=queue.poll().listFiles();
if (flist == null || flist.length == 0) {
continue;
}
//将目录下的一层全部加入队列
for(File f:flist)
{
queue.add(f);
}
}
}
1.Java编程思想
2.http://tutorials.jenkov.com/java-io/file.html