文章目录
- Java 文件操作
- 构造方法
- 文件属性操作
- 文件内容操作
- InputStream
- Reader
- OutputStream
- Writer
- 更多案例
- 文件查找
- 普通文件的复制
Java 文件操作
Java 中通过 java.io.File
类来对文件进行描述。
构造方法
构造方法 | 说明 |
---|---|
File(String pathname) | 通过路径名字符串来创建 File 实例 |
File(String parent, String child) | 从父路径名字符串和子路径名字符串创建 File 实例 |
File(File parent, String child) | 从父抽象路径名和子路径名字符串创建 File 实例 |
注意:创建 File 实例不等于创建文件
文件属性操作
方法 | 说明 |
---|---|
String getParent() | 返回父路径名字符串 |
String getName() | 返回该抽象路径名表示的文件或目录的名称 |
String getPath() | 将此抽象路径名转换为路径名字符串 |
String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串 |
String getCanonicalPath() | 返回此抽象路径名的规范路径名字符串 |
boolean exists() | 测试此抽象路径名表示的文件或目录是否存在 |
boolean isDirectory() | 测试此抽象路径名表示的文件是否为目录 |
boolean isFile() | 测试此抽象路径名表示的文件是否为普通文件 |
boolean createNewFile() | 当且仅当具有此名称的文件还不存在时,原子地创建一个由该抽象路径名命名的新的空文件。 |
boolean delete() | 删除由该抽象路径名表示的文件或目录 |
void deleteOnExit() | 请求在虚拟机终止时删除由该抽象路径名表示的文件或目录 |
String[] list() | 返回该抽象路径名下的文件名 |
File[] listFiles() | 返回一个抽象路径名数组,表示该抽象路径名所表示的目录中的文件 |
boolean mkdir() | 创建以此抽象路径名命名的目录 |
boolean mkdirs() | 创建以此抽象路径名命名的目录,如果必要,会创建中间目录 |
boolean renameTo(File dest) | 重命名由该抽象路径名表示的文件 |
boolean canRead() | 测试应用程序是否可以读取由该抽象路径名表示的文件 |
boolean canWrite() | 测试应用程序是否可以修改由该抽象路径名表示的文件 |
示例:
public static void main(String[] args) throws IOException {File file = new File("d:/test.txt");System.out.println(file.getParent()); // d:\System.out.println(file.getName()); // test.txtSystem.out.println(file.getPath()); // d:\test.txtSystem.out.println(file.getAbsolutePath()); // d:\test.txtSystem.out.println(file.getCanonicalPath()); // D:\test.txt
}
public static void main(String[] args) throws IOException {File file = new File("helloworld.txt");System.out.println(file.exists()); // falseSystem.out.println(file.isDirectory()); // falseSystem.out.println(file.isFile()); // falseSystem.out.println("=============================");// 创建文件file.createNewFile();System.out.println(file.exists()); // trueSystem.out.println(file.isDirectory()); // falseSystem.out.println(file.isFile()); // true
}
public static void main(String[] args) {File file = new File("helloworld.txt");// 删除文件file.delete();System.out.println(file.exists()); // false
}
public static void main(String[] args) throws IOException, InterruptedException {File file = new File("helloworld.txt");// 把文件创建回来file.createNewFile();// 在程序退出前删除file.deleteOnExit();Thread.sleep(5000);System.out.println(file.exists()); // true
}
public static void main(String[] args) {// 创建目录File file = new File("test");System.out.println(file.exists()); // falseSystem.out.println(file.isDirectory()); // falseSystem.out.println("========================");file.mkdir();System.out.println(file.exists()); // trueSystem.out.println(file.isDirectory()); // true
}
public static void main(String[] args) {// 创建多级目录File file = new File("test/a/b/c");System.out.println(file.exists()); // falseSystem.out.println(file.isDirectory()); // falseSystem.out.println("========================");file.mkdirs();System.out.println(file.exists()); // trueSystem.out.println(file.isDirectory()); // true
}
public static void main(String[] args) throws IOException {// 文件重命名File file1 = new File("test1.txt");File file2 = new File("test2.txt");file1.createNewFile(); // 创建 test1.txtfile1.renameTo(file2); // 重命名成 test2.txt
}
文件内容操作
相关的类:
- 字节流:
InputStream
OutputStream
,用于操作二进制文件 - 字符流:
Reader
Writer
,用于操作文本文件
InputStream
方法 | 说明 |
---|---|
int read() | 从输入流中读取下一个字节的数据。值字节以 int 形式返回,其范围为 0 到 255。如果由于到达流的末尾而没有可用的字节,则返回值 -1。此方法会阻塞,直到输入数据可用、检测到流的末尾或引发异常为止。 |
int read(byte b[]) | 从输入流中读取一定数量的字节,并将其存储到数组 b 中,并且尽可能把 b 填满。实际读取的字节数以整数形式返回。此方法会阻塞,直到输入数据可用、检测到文件结尾或引发异常为止。 |
int read(byte b[], int off, int len) | 也是把读到的字节往 b 里塞,从 off 的位置开始塞,最多塞 len 个字节 |
InputStream
是一个抽象类,通过 new 它的子类 FileInputStream
来实例化
// 文件内容:hello
public static void main(String[] args) throws IOException {// 打开文件InputStream inputStream = new FileInputStream("test2.txt");// 读取文件while (true) {int b = inputStream.read();if (b == -1) {break;}System.out.println(b);}// 关闭文件inputStream.close();
}
/*输出:
104
101
108
108
111
*/
这正是 hello 的 ASCII 码
要想把字节流还原成原来的文本,需要手动处理:
public static void main(String[] args) throws IOException {// 打开文件InputStream inputStream = new FileInputStream("test2.txt");// 读取文件byte[] b = new byte[1024];int len = inputStream.read(b);// 还原成文本String s = new String(b, 0, len, StandardCharsets.UTF_8);System.out.println(s);// 关闭文件inputStream.close();
}
Reader
方法 | 说明 |
---|---|
int read(java.nio.CharBuffer target) | 尝试将字符读取到指定的字符缓冲区中 |
int read() | 读取单个字符。此方法将阻塞,直到字符可用、发生I/O错误或到达流的末尾 |
int read(char cbuf[]) | 将字符读取到数组中。此方法将一直阻塞,直到某个输入可用、出现I/O错误或到达流的末尾 |
int read(char cbuf[], int off, int len) | 将字符读入数组的一部分。此方法将一直阻塞,直到某个输入可用、出现I/O错误或到达流的末尾 |
使用 FileReader
实例化
例:Reader 直接读取到文本
public static void main(String[] args) throws IOException {Reader reader = new FileReader("test2.txt");char[] buffer = new char[1024];int len = reader.read(buffer);for (int i = 0; i < len; ++i) {System.out.println(buffer[i]);}reader.close();
}
其实读文件最方便的写法,是使用 Scanner:
这个我们在标准输入的时候用过,只要把 System.in
换成其他 InputStream
public static void main(String[] args) throws IOException {InputStream inputStream = new FileInputStream("test2.txt");Scanner scanner = new Scanner(inputStream);String s = scanner.next();System.out.println(s);inputStream.close();
}
技巧:使用 try with resources 关闭文件
try (InputStream inputStream = new FileInputStream("test2.txt")){// ......
} catch (IOException e) {e.printStackTrace();
}
OutputStream
方法 | 说明 |
---|---|
void write(int b) | 将指定的字节写入此输出流 |
void write(byte b[]) | 将指定字节数组中的 b.length 个字节写入此输出流 |
void write(byte b[], int off, int len) | 从偏移量为 off 的指定字节数组中写入 len 个字节到此输出流 |
public static void main(String[] args) throws IOException {try (OutputStream outputStream = new FileOutputStream("test2.txt")) {outputStream.write('a');outputStream.write('b');outputStream.write('c');}
}
如果要输出一个字符串,那么需要转为字节数组:
public static void main(String[] args) throws IOException {try (OutputStream outputStream = new FileOutputStream("test2.txt")) {String s = "你好";outputStream.write(s.getBytes());}
}
注意:打开文件会清空文件内容,写的时候并不会
Writer
方法 | 说明 |
---|---|
void write(int c) | 写入单个字符 |
void write(char cbuf[]) | 写入一个字符数组 |
void write(char cbuf[], int off, int len) | 写入字符数组的一部分 |
void write(String str) | 写入字符串 |
void write(String str, int off, int len) | 写入字符串的一部分 |
public static void main(String[] args) throws IOException {try (Writer writer = new FileWriter("test2.txt")) {writer.write("hello world");}
}
使用 PrintWriter 包装一下:
public static void main(String[] args) throws IOException {try (OutputStream outputStream = new FileOutputStream("test2.txt")) {PrintWriter printWriter = new PrintWriter(outputStream);// 此处 printWriter 的用法就和 System.out 类似了printWriter.println("aaa");printWriter.flush();}
}
注意:PrintWriter
自带缓冲区,如果你写的内容太短,可能需要 flush
一下
更多案例
文件查找
递归查找目录下的所有文件,将文件名包含指定字符串的文件删除
import java.io.*;
import java.util.Scanner;public class demo {public static void main(String[] args) throws IOException {System.out.println("请输入要扫描的路径:");Scanner scanner = new Scanner(System.in);String rootPath = scanner.next();File root = new File(rootPath);if (!root.exists()) {System.out.println("输入的路径不存在");return;}System.out.println("请输入要删除的文件名(或部分):");String toDelete = scanner.next();// 递归删除文件scanDir(root, toDelete);}public static void scanDir(File rootDir, String toDelete) throws IOException {File[] files = rootDir.listFiles();if (files == null) {return;}for (File f : files) {if (f.isDirectory()) {scanDir(f, toDelete);} else {tryDelete(f, toDelete);}}}public static void tryDelete(File f, String toDelete) throws IOException {if (f.getName().contains(toDelete)) {System.out.println("是否删除文件(y/n):" + f.getCanonicalPath());Scanner scanner = new Scanner(System.in);String choice = scanner.next();if (choice.equals("y")) {f.delete();}}}
}
普通文件的复制
import java.io.*;
import java.util.Scanner;public class demo {public static void main(String[] args) throws IOException {System.out.println("请输入要复制的文件路径:");Scanner scanner = new Scanner(System.in);String srcPath = scanner.next();File srcFile = new File(srcPath);if (!srcFile.exists()) {System.out.println("文件不存在");return;}if (!srcFile.isFile()) {System.out.println("不是普通文件");return;}System.out.println("请输入目标路径:");String destPath = scanner.next();File destFile = new File(destPath);if (destFile.exists()) {System.out.println("目标已经存在");return;}// 开始复制try (InputStream inputStream = new FileInputStream(srcFile);OutputStream outputStream = new FileOutputStream(destFile)) {byte[] buf = new byte[1024];while (true) {int len = inputStream.read(buf);if (len == -1) {// 拷贝完成break;}outputStream.write(buf, 0, len);}}System.out.println("复制完成");}
}