/*
求解:关于在盘符中搜索文件(listFiles()方法)出现NullPointerException
需求:通过键盘将一个指定目录下的所有指定格式文件(如.java、avi)的绝对路径,
存储到一个文本文件中。建立一个java文件列表文件。
键盘的录入格式为:
1、父级目录-文件名/文件格式/字段\r\n文件名/文件格式/字段\r\n文件名/文件格式/字段......
父级目录-文件名/文件格式/字段\r\n父级目录\r\n父级目录\r\n父级目录......
如:f:/text-txt
c:\\music\list-我的心好冷.mp3
e:\-.java (遍历 e 盘中带字段 .java 的文件)
doc
.dll
d:\
2、文件名/文件格式/字段 父级目录\r\n文件名/文件格式/字段\r\n文件名/文件格式/字段......
文件名/文件格式/字段 父级目录\r\n父级目录\r\n父级目录\r\n父级目录......
思路:
1、通过键盘输入指定目录和文件字段。
2、对指定的目录进行递归。
3、获取递归过程中所有的java文件的路径。
4、将这些路径存储到集合中。
5、将集合中的数据写入到一个文件中。
步骤:
1、定义类SearchFile,查找某文件夹中的文件。
2、提供对外访问方法search。
3、定义方法inputDir,使用键盘写入数据,需要InputStreamReader转换流来将字节数据转换成字符串数据。
4、定义方法spiltString,来区分输入的字符串中的目录和文件字段。
5、定义方法fileToList,对指定目录递归,将遍历到的所有目录存入数组files中,
并将所有遍历到的绝对目录添加到list集合中。
6、定义方法writeFile,通过输出流 BufferedWriter 将获取的绝对路径写入指定的 .txt文件中。
注:尽量缩小盘符查找,过大容易报异常。
question:在进行全盘遍历的时候,有些盘遍历一会儿后会报 NullPointerException,
偶尔运行又是正常的,怎么解决?
该异常发生在fileToList()的循环体中。
如:f:\-dll c:\-exe
*/
import java.util.*;
import java.io.*;
class SearchFile
{
private String filetype; //指向文件类型的成员变量
private String directions; //指向一行字符串的成员变量
//该功能实现了使用键盘输入需要查找的文件夹中的某/某类型文件
public void search()
{
inputDir();
}
private void inputDir()
{
BufferedReader bufr = null; //声明空输入流
List<File> list = null; //声明空list集合
try
{
//使用转换流 InputStreamReader,将键盘录入的字节流数据转换成字符流数据来处理
bufr = new BufferedReader(new InputStreamReader(System.in));
//集合中的数据要在最后一步进行清空,否则最后数据越积越多。
list = new ArrayList<File>();
String line = null;
//获取键盘输入的一行字符串,并判断是否为空。
while ((line=bufr.readLine())!=null)
{
if ("over".equals(line))
break;
else
{
//切割line字符串,并将切割后的子串分别存入files数组中
spiltString(line);
System.out.println("路径: "+directions+"--------文件类型: "+filetype);
File dir = null;
try
{
//将键盘输入数据作为值传递给该文件类对象,若引用file指向空则报异常
dir = new File(directions);
}
catch (NullPointerException e)
{
throw new NoSuchFileException("目录不存在!");
}
fileToList(dir,list,filetype); //throws NullPointerException
consFile(list,filetype);
}
}
}
catch (IOException e)
{
throw new NoSuchFileException("文件名格式书写错误!");
}
finally
{
try
{
if (bufr!=null)
bufr.close();
}
catch (IOException e)
{
throw new RuntimeException("输入流关闭失败!");
}
}
}
//功能实现了将路径存入集合中
private void fileToList(File dir, List<File> list, String filetype) throws NullPointerException
{
//遍历文件夹中的文件和子文件夹,将遍历的目录(包括父目录和绝对目录)作为对象存入数组中
File[] files = dir.listFiles();
//高级for循环,迭代File[]数组,将其中的目录依次赋值给f
for (File f : files)
{
//获取的file值是目录就继续递归,否者就将file文件存入List集合中
if (f.isDirectory())
fileToList(f,list,filetype);
else if (f.getName().contains(filetype))
list.add(f);
//System.out.println("file: "+f);
}
}
//创建文件
private void consFile(List<File> list, String filetype)
{
FileWriter fw = null;
try
{
fw = new FileWriter("f:"+File.separator+filetype+".txt");
//调用写入数据方法
write(fw,list,filetype);
}
catch (IOException e)
{
//System.out.println("路径为:"+"f:"+File.separator+filetype+".txt");
throw new NoSuchFileException("文件创建失败,请检查路径是否存在!");
}
finally
{
try
{
if (fw!=null)
fw.close();
}
catch (IOException e)
{
throw new RuntimeException("输出流关闭失败!");
}
}
}
//向文件中写入数据
private void write(Writer writer, List<File> list, String filetype)
{
//PrintWriter中的两个参数的意义:前者是将绝对路径封装成对象,并创建文件,会替换盖掉原文件。
//true是:表示在每次向文件中写入数据时就刷新一次。separator:跨平台目录分隔符。
PrintWriter out = new PrintWriter(writer,true);
int count = 0; //定义计数器
//高级for循环,迭代list集合,将其中的数据依次赋值给f
for (File f : list)
{
//获取file文件的绝对路径
String path = f.getAbsolutePath();
out.println(path);
count++;
}
out.println(); //换行,其实底层调用的就是newLine()
out.write("一共有"+filetype+"文件"+count+"个");
out.close(); //不需要进行处理,方法中已经处理过了
//每遍历完一个文件夹(或最子文件夹)就清空一次集合,保证在下一次向集合中添加数据的有效性。
list.clear();
}
//切割字符串
private void spiltString(String line)
{
String[] arr = new String[2];
arr = line.split("-");
for (int i=0; i<arr.length; i++)
{
File f = new File(arr);
//判断目录是否存在,若不存在file变量让然为null。
if (f.isDirectory())
directions = f.toString();
else
filetype = f.toString();
}
}
}
//自定义运行时异常类
class NoSuchFileException extends RuntimeException
{
NoSuchFileException(String message)
{
super(message);
}
}
class SearchFileDemo
{
public static void main(String[] args)
{
SearchFile sf = new SearchFile();
sf.search();
}
}
|