文件操作和 IO - 一些具体的使用栗子
栗子一:
查找硬盘上的文件位置,给定一个文件名,去指定的目录中进行搜索,找到文件名匹配的结果,并且打印出完整的路径。文件系统的目录结构是“树型”结构。既然是搜索,就会涉及到遍历,针对树的遍历,又要涉及递归。(这里的递归,可能比二叉树复杂一点点,目录中有几个子目录,就递归几次)
代码如下:
public static void main(String[] args) {
// 1. 输入必要的信息
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要搜索的文件名:");
String fileName = scanner.next();
System.out.println("请输入要搜索的目录");
String rootPath = scanner.next();
File rootFile = new File(rootPath);
if (!rootFile.isDirectory()) {
System.out.println("输入的目录有误!");
return;
}
// 2. 有了要搜索的路径之后,就可以按照 递归 的方式来进行搜索了
// 知道递归的七点,还需要知道要查询的文件名
scanDir(rootFile, fileName);
}
private static void scanDir(File rootFile, String fileName) {
// 1. 把当前目录中的文件和子目录都列出来
File[] files = rootFile.listFiles();
if (null == files) {
// 该目录为空 直接返回
return;
}
// 2. 遍历上述 files,判定每一个 file 是目录还是文件
for (File f : files) {
System.out.println("当前遍历到" + f.getAbsolutePath());
if (f.isFile()) {
// 普通文件,判定文件名是否是搜索的文件
if (fileName.equals(f.getName())) {
System.out.println("找到了符合要求的文件!!" + f.getAbsolutePath());
}
} else if(f.isDirectory()) {
// 目录文件,需要进一步递归
scanDir(f,fileName);
} else {
;
}
}
}
这里的递归,就是进行树的遍历,把目录中,以及其中的子目录,所有的文件,都遍历一次,看是否有符合需要的。我们这个只能称为“遍历”,谈不上前中后序~~~此处是 N 叉树,并且每个节点上也有很多文件,访问操作出现的时机,对于这里来说,访问,指的就是判定文件名这压根的操作~~~(像 everything 这样的程序,就是需要遍历我们的目录来获取到我们的文件 / 目录的结构信息,遍历的过程就是类似于上述的递归过程~~~)
栗子二:
实现文件复制,把一个文件复制一下, 称为另一个文件。把第一个文件以读方式打开,依次读取出来这里的每个字节,再把读到的内容,写入另一个文件里面。
代码示例:
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要复制的源文件:");
String srcPath = scanner.next();
System.out.println("请输入要复制的目标文件:");
String destPath = scanner.next();
// 合法性判断
// 1. srcPath 对应的文件是否存在
File srcFile = new File(srcPath);
if (!srcFile.isFile()) {
System.out.println("源文件路径有误");
return;
}
// 2. destPath 并不要求对应的文件存在,但是要求目录得存在
File destFile = new File(destPath);
if (!destFile.getParentFile().isDirectory()) {
System.out.println("目标路径有误");
return;
}
// 复制操作
try (InputStream inputStream = new FileInputStream(srcFile) ;
OutputStream outputStream = new FileOutputStream(destFile)) {
while (true) {
byte[] buffer = new byte[1024];
int n = inputStream.read(buffer);
if (-1 == n) {
// 读取完毕
break;
}
// 把读到的内容写到 outputStream 中
outputStream.write(buffer,0,n);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
并且上述代码中,是按照二进制的方式进行复制的,可以复制任何的文件。
栗子三:
第三个栗子,是将上面的两个栗子结合一下。
第一个栗子,是在目录中搜索名字匹配的文件。第二个栗子,是直接复制文件。
第三个栗子,还是在目录中搜索,按照文件内容的方式搜索,用户输入一个目录,一个要搜索的词,遍历文件的过程中,如果文件包含了要搜索的词(这个匹配过程,就需要将文件的内容读取出来,再在文件的内容中进行查找),就把文件的路径打印出来。
代码示例:
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要搜索的目录:");
String rootPath = scanner.next();
System.out.println("请输入要查询的词:");
String word = scanner.next();
File rootFile = new File(rootPath);
if (!rootFile.isDirectory()) {
System.out.println("输入的要搜索的目录");
return;
}
scanDir(rootFile, word);
}
private static void scanDir(File rootFile, String word) {
File[] files = rootFile.listFiles();
if (null == files) {
// 目录下为空
return;
}
for (File f : files) {
System.out.println("当前遍历到:" + f.getAbsolutePath());
if (f.isFile()) {
// 在文件内容中搜索
searchInFile(f, word);
} else if(f.isDirectory()) {
// 递归遍历
scanDir(f,word);
} else {
;
}
}
}
private static void searchInFile(File f, String word) {
// 通过这个方法 在文件的内部中搜索关键词
// 1. 把文件的内容都读出来
try (InputStream inputStream = new FileInputStream(f)) {
StringBuilder stringBuilder = new StringBuilder();
while (true) {
byte[] buffer = new byte[1024];
int n = inputStream.read(buffer);
if (-1 == n) {
// 读完数据了!
break;
}
// 在 while 循环里面 每一次循环都值是取出文件的一部分
// 需要把文件的内容整体的拼接在一起
String s = new String(buffer,0,n);
stringBuilder.append(s);
}
// 2.当文件读取完毕之后,循环结束,StringBuilder 就是包含文件整个内容的字符串了
if (stringBuilder.indexOf(word) == -1) {
// 没找到
return;
}
// 找到了 打印文件路径
System.out.println("找到了!" + word + "存在于" + f.getAbsolutePath());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
补充:
三个栗子中,对输入进来的路径的合法性判断的逻辑,是非常重要的,实际开发中不能随便省略!!!