目录
摘要
通过Java对文件进行读、写、删、复制等操作。
Java 中通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述。注意,有 File 对象,并不 代表真实存在该文件
1.文件的概述
我们通常说的文件一般是指存储在硬盘上的普通文件,形如 .txt .jpg .mp4 .rar 等这些文件都是普通文件,都在硬盘上存储着。
在计算机中,文件可能是一个广义的概念,就不只是包含普通文件,还包含文件夹等。
1.1文本文件
文本文件里面存储的是字符,本质上也是存储字节的。我们将一个文件用记事本打开,打开显示的不是乱码就是文本文件。如 .txt .c .java .sql 等都属于文文文件。如下所示
1.2二进制文件
二进制文件里面存储的是字节。使用记事本打开之后是乱码,如下图所示。如 .doc .ppt .exe .jpg .png .zip 等文件都是二进制文件。
1.3目录结构
计算机里面,文件是通过“文件系统”模块来负责的,使用的是N叉树结构。
如果是一个普通文件,则是树的叶子节点。
如果是一个目录文件,目录中就可以包含子树,这个目录就是非叶子节点,这个树每个节点上的子树都可以有N个。
这就是一个N叉树
在操作系统中,通过“路径”这样的概念来描述一个具体文件/目录的位置
1.绝对路径:以盘符开头的,如
C:\Intel\Logs\DXP.exe
C:\Program Files\Google\Chrome\Application
2.相对路径 以 . 或者 .. 开头的。其中 . 表示当前路径。 ..表示当前路径的父目录。
相对路径就是从基准目录出发,按照一个路径找到的对应文件。
例如以C:\Intel\Logs为基准目录,找到 DXP.exe 。则 ./DXP.exe 中的 . 就是基准目录
还是以C:\Intel\Logs 为基准目录,找到 ddz.zip 。则 ../ddz.zip 中的 .. 就表示基准目录的上一级路径C:\Intel
2.Java操作文件
文件系统相关的操作是指通过“文件资源管理器” 能够完成一些功能,如:列出目录中有哪些文件、创建文件、创建目录、删除文件、重命名文件等。
在Java中提供一个File 类,通过这个类来完成上诉操作,File 的构造方法能够传入一个路径,来指定一个文件。
2.1 file的构造
import java.io.File;
import java.io.IOException;
//file 的构造
public class Test1 {
public static void main(String[] args) throws IOException {
File f = new File("d:/test.txt");
System.out.println(f.getParent());//获取到文件的父目录
System.out.println(f.getName());//获取到文件名
System.out.println(f.getPath());//获取到文件路径(构造file 的时候的指定路径)
System.out.println(f.getAbsolutePath());//获取绝对路径
System.out.println(f.getCanonicalFile());//获取绝对路径
System.out.println("------------------");
File f2 = new File("./test.txt");
System.out.println(f2.getParent());//获取到文件的父目录
System.out.println(f2.getName());//获取到文件名
System.out.println(f2.getPath());//获取到文件路径(构造file 的时候的指定路径)
System.out.println(f2.getAbsolutePath());//获取绝对路径
System.out.println(f2.getCanonicalFile());//获取绝对路径
}
}
2.2判断文件是否存在
在这里,我并没有创建test.txt文件,所以结果都是false
import java.io.File;
public class Test2 {
public static void main(String[] args) {
File f = new File("d/test.txt");
System.out.println(f.exists());//判断 File 对象描述的文件是否真实存在
System.out.println(f.isDirectory());//判断 File 对象代表的文件是否是一个目录
System.out.println(f.isFile());//判断 File 对象代表的文件是否是一个普通文件
}
}
2.3文件的创建
通过 createNewFile() 方法进行创建
import java.io.File;
import java.io.IOException;
public class Test3 {
public static void main(String[] args) throws IOException {
File f = new File("./test.txt");
System.out.println(f.exists());//判断文件是否存在,false
System.out.println("创建文件");
f.createNewFile();
System.out.println("创建结束");
System.out.println(f.exists());//判断文件是否存在,true
}
}
运行
创建成功
2.4文件的删除
import java.io.File;
public class Test4 {
public static void main(String[] args) {
File f = new File("./test.txt");
System.out.println(f.exists());//判断文件是否存在,true
f.delete();
if(!f.exists()) {
System.out.println("删除成功");
}
}
}
刚开始我们是已经创建好test.txt文件的,所以是true ,然后我们再删除,经过判断输出“删除成功”
2.5目录的创建
import java.io.File;
public class Test5 {
public static void main(String[] args) {
File f = new File("./abc");
f.mkdir();//创建abc目录
System.out.println(f.isDirectory());
}
}
将目录的名字更改
import java.io.File;
public class Test6 {
public static void main(String[] args) {
File f = new File("./abc");
File f2 = new File("./aaa");
f.renameTo(f2);
}
}
3.文件的读取
用到的是 InputStream 。Stream是流对象,针对文件内容的读写,Java标准库提供了一组类,按照文件的内容,分为两个系列
1.字节流对象:针对二进制文件,以字节为单位进行读写,读InoutStream, 写 OutoutStream
2.字符流对象:针对文本文件,以字符为单位来读写,读Reader, 写Writer
以上写的都是抽象类,是以 File....开头类的子类
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test7 {
public static void main(String[] args) {
//构造方法需要指定打开文件的路径
//可以是绝对路径或者相对路径,还可以是file对象
InputStream inputStream = null;
try {
//1.创建对象,同时也在打开文件
inputStream = new FileInputStream("./test.txt");
//2.尝试一个一个字节读,读完整个文件
while (true) {
int b = inputStream.read();
if (b == -1) {
//读到文件末尾
break;
}
System.out.println(b);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//3.读完之后关闭文件,释放资源
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
可以将上述代码优化
try (InputStream inputStream = new FileInputStream("test.txt")) {
//一次读取若干个
byte[] buffer = new byte[1024];
int len;
while (true) {
len = inputStream.read();
if (len == -1) {
//如果是 -1 ,则读取完毕
break;
}
for (int i = 0; i < len; i++) {
System.out.println(buffer[i]);
}
}
}catch (IOException e) {
e.printStackTrace();
}
4.写文件
利用字节流对文件进行写
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Test8 {
public static void main(String[] args) {
//使用字节流,写文件
try (OutputStream outputStream = new FileOutputStream("./test.txt")) {
outputStream.write(98);
outputStream.write(99);
outputStream.write(100);
}catch (IOException e) {
e.printStackTrace();
}
}
}
在执行程序之前,我们先将test.txt 文件内的内容清空,然后执行代码进行写文件
4.1按照字符来读写
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
//按照字符来读写
public class Test9 {
public static void main(String[] args) {
try (Reader reader = new FileReader("./test.txt")) {
//按照字符来读
while (true) {
char[] buffer = new char[1024];
int len = reader.read(buffer);
if (len == -1) {
break;
}
//写
/*
for (int i = 0; i < len; i++) {
System.out.println(buffer[i]);
}
*/
//如果传入的数组是 byte 数组,因使用 utf-8 字符集,避免乱码
String s = new String(buffer,0,len);
System.out.println(s);
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
4.2按照字符来写
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
//按照字符来写
public class Test10 {
public static void main(String[] args) {
try (Writer writer = new FileWriter("./test.txt")) {
writer.write("Fly Upward");
}catch (IOException e) {
e.printStackTrace();
}
}
}
5.文件的查找并删除
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
//实现查找文件并删除
public class Test11 {
public static void main(String[] args) {
//1.先输入要扫描的目录,以及要删除的文件名
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要扫描的路径");
String rootDirPath = scanner.next();
System.out.println("请输入要删除的文件名:");
String toDeleteName = scanner.next();
File rootDir = new File(rootDirPath);
if (!rootDir.isDirectory()) {
System.out.println("输入路径有误");
return;
}
//2.遍历目录,把指定目录中的所有文件和子目录都遍历一遍,从而找到要删除的文件
scanDir(rootDir,toDeleteName);
}
private static void scanDir(File rootDir, String toDeleteName) {
//1.先列出 rootDir 中有哪些内容
File[] files = rootDir.listFiles();
if (files == null) {
//空目录
return;
}
//遍历当前列出的这些内容. 如果是普通文件, 就检测文件名是否是要删除的文件.
// 如果是目录, 就递归的进行遍历
for (File f : files) {
if (f.isFile()) {
if (f.getName().contains(toDeleteName)) {
//不要求名字完全一样, 只要文件名中包含了关键字即可删除
// 就进行删除操作
deleteFile(f);
}
} else if (f.isDirectory()) {
//目录就递归的进行遍历
scanDir(f,toDeleteName);
}
}
}
private static void deleteFile(File f) {
try {
System.out.println(f.getCanonicalPath() + "确认要删除吗?(Y/y)");
Scanner scanner = new Scanner(System.in);
String choice = scanner.next();
if (choice.equals("Y") || choice.equals("y")) {
f.delete();
System.out.println("文件删除成功!");
} else {
System.out.println("文件取消删除!");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果
6.文件的复制
import java.io.*;
import java.util.Scanner;
//复制文件
public class Test12 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要拷贝的原路径文件");
String src = scanner.next();
System.out.println("请输入要拷贝的目标路径");
String dest = scanner.next();
File srcFile = new File(src);
if (!srcFile.isFile()) {
System.out.println("输入的原路径不正确");
return;
}
// 此处不太需要检查目标文件是否存在. OutputStream 写文件的时候能够自动创建不存在的文件.
// 2. 读取源文件, 拷贝到目标文件中
try (InputStream inputStream = new FileInputStream(src)) {
try (OutputStream outputStream = new FileOutputStream(dest)) {
// 把 inputStream 中的数据读出来, 写入到 outputStream 中
byte[] buffer = new byte[1024];
while (true) {
int len = inputStream.read(buffer);
if (len == -1) {
//读取完毕
break;
}
// 写入的时候, 不能把整个 buffer 都写进去. 毕竟 buffer 可能是只有一部分才是有效数据.
outputStream.write(buffer, 0, len);
}
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果
7.扫描指定目录
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Scanner;
public class Test14 {
public static void main(String[] args) throws IOException {
//1.输入要扫描的文件路径
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要扫描的路径");
String rootDirPath = scanner.next();
System.out.println("请输入要查询的关键词");
String word = scanner.next();
File rootDir = new File(rootDirPath);
if (!rootDir.isDirectory()) {
System.out.println("输入的路径非法");
return;
}
//2.递归遍历
scanDir(rootDir,word);
}
private static void scanDir(File rootDir, String word) throws IOException {
//1.列出rootDir 有哪些内容
File[] files = rootDir.listFiles();
if (files == null) {
return;
}
//2. 遍历每个元素, 针对普通文件和目录分别进行处理.
for (File f : files) {
if (f.isFile()) {
// 针对文件进行内容查找
if (containsWord(f,word)) {
System.out.println(f.getCanonicalFile());
}
} else if (f.isDirectory()) {
// 针对目录进行递归
scanDir(f,word);
}
}
}
private static boolean containsWord(File f, String word) {
StringBuilder stringBuilder = new StringBuilder();
// 把 f 中的内容都读出来, 放到一个 StringBuilder 中
try (Reader reader = new FileReader(f)) {
char[] buffer = new char[1024];
while (true) {
int len = reader.read(buffer);
if (len == -1) {
break;
}
// 把这一段读到的结果, 放到 StringBuilder 中
stringBuilder.append(buffer, 0, len);
}
}catch (IOException e) {
e.printStackTrace();
}
// indexOf 返回的是子串的下标. 如果 word 在 stringBuilder 中不存在, 则返回下标为 -1
return stringBuilder.indexOf(word) != -1;
}
}
运行结果