Java 文件操作详解
在 Java 编程中,文件操作是不可或缺的一部分。无论是读取配置文件、写入日志,还是处理用户上传的文件,文件操作都是我们日常开发中频繁使用的功能。为了简化文件操作,我们通常会在项目中创建一个名为 FileUtil
或 FileUtils
的工具类。本文将详细介绍 Java 中的文件操作,从 java.io.File
类到 RandomAccessFile
,再到第三方库如 Apache Commons IO 和 Hutool 的使用。
1. java.io.File
类
java.io.File
类是 Java 中专门用于文件操作的类。需要注意的是,File
类只能对文件本身进行操作,不能对文件内容进行读写。要操作文件内容,必须借助输入输出流(如 FileInputStream
和 FileOutputStream
)。
File
类主要用于文件和目录的创建、查找和删除等操作。它可以表示文件夹(目录)或文件。
1.1 构造方法
File
类提供了三种常用的构造方法:
File(String pathname)
:通过给定的路径字符串创建File
实例。File(String parent, String child)
:通过父路径字符串和子路径字符串创建File
实例。File(File parent, String child)
:通过父路径File
对象和子路径字符串创建File
实例。
/**
* File类的构造器
*/
private static void testFileConstructors() {
// 文件路径名
String path = "JavaSE/resourses/123.txt";
File file1 = new File(path);
// 文件路径名
String path2 = "JavaSE/resourses/1/2.txt";
File file2 = new File(path2); //-------------相当于JavaSE/resourses/1/2.txt
// 通过父路径和子路径字符串
String parent = "JavaSE/resourses/aaa";
String child = "bbb.txt";
File file3 = new File(parent, child); //--------相当于JavaSE/resourses/aaa/bbb.txt
// 通过父级File对象和子路径字符串
File parentDir = new File("JavaSE/resourses/aaa");
String child2 = "bbb.txt";
File file4 = new File(parentDir, child2); //--------相当于JavaSE/resourses/aaa/bbb.txt
}
1.2 常用方法
File
类的常用方法主要分为获取功能、判断功能、创建与删除功能、目录遍历等。
- 获取功能:
getAbsolutePath()
:返回文件的绝对路径。getPath()
:返回文件的构造路径。getName()
:返回文件或目录的名称。length()
:返回文件的长度(字节数)。
/**
* 获取功能
*/
private static void testGetFuncMetonds() {
File f = new File("JavaSE/resourses/aaa/bbb.java");
System.out.println("文件绝对路径:" + f.getAbsolutePath());
System.out.println("文件构造路径:" + f.getPath());
System.out.println("文件名称:" + f.getName());
System.out.println("文件长度:" + f.length() + "字节");
File f2 = new File("JavaSE/resourses/aaa");
System.out.println("目录绝对路径:" + f2.getAbsolutePath());
System.out.println("目录构造路径:" + f2.getPath());
System.out.println("目录名称:" + f2.getName());
System.out.println("目录长度:" + f2.length());
}
- 判断功能:
exists()
:判断文件或目录是否存在。isDirectory()
:判断是否为目录。isFile()
:判断是否为文件。
/**
* 判断功能
*/
private static void testBoolFuncMethods() {
File file = new File("JavaSE/resourses/fw.txt");
// 判断文件或目录是否存在
if (file.exists()) {
System.out.println("文件或目录存在");
} else {
System.out.println("文件或目录不存在");
}
// 判断是否是目录
if (file.isDirectory()) {
System.out.println("是目录");
} else {
System.out.println("不是目录");
}
// 判断是否是文件
if (file.isFile()) {
System.out.println("是文件");
} else {
System.out.println("不是文件");
}
}
- 创建与删除功能:
createNewFile()
:创建新文件。delete()
:删除文件或目录。mkdir()
:创建一级目录。mkdirs()
:创建多级目录。
/**
* 创建与删除功能
*
* @throws IOException
*/
private static void testCreateAndDeleteFuncMethods() throws IOException {
// 创建文件
File file = new File("JavaSE/resourses/test.txt");
if (file.createNewFile()) {
System.out.println("创建文件成功:" + file.getAbsolutePath());
} else {
System.out.println("创建文件失败:" + file.getAbsolutePath());
}
// 删除文件
if (file.delete()) {
System.out.println("删除文件成功:" + file.getAbsolutePath());
} else {
System.out.println("删除文件失败:" + file.getAbsolutePath());
}
// 创建多级目录
File directory = new File("JavaSE/resourses/example/subdir1/subdir2");
if (directory.mkdirs()) {
System.out.println("创建目录成功:" + directory.getAbsolutePath());
} else {
System.out.println("创建目录失败:" + directory.getAbsolutePath());
}
}
- 目录遍历:
list()
:返回目录下的文件名数组。listFiles()
:返回目录下的文件和子目录的File
数组。
/**
* 目录遍历
*/
private static void testListFuncMethods() {
File directory = new File("JavaSE/resourses");
// 列出目录下的文件名
String[] files = directory.list();
System.out.println("目录下的文件名:");
for (String file : files) {
System.out.println(file);
}
// 列出目录下的文件和子目录
File[] filesAndDirs = directory.listFiles();
System.out.println("目录下的文件和子目录:");
for (File fileOrDir : filesAndDirs) {
if (fileOrDir.isFile()) {
System.out.println("文件:" + fileOrDir.getName());
} else if (fileOrDir.isDirectory()) {
System.out.println("目录:" + fileOrDir.getName());
}
}
}
/**
* 递归遍历
*
* @param directory
*/
private static void testTraverseDirectory(File directory) {
// 列出目录下的所有文件和子目录
File[] filesAndDirs = directory.listFiles();
// 遍历每个文件和子目录
for (File fileOrDir : filesAndDirs) {
if (fileOrDir.isFile()) {
// 如果是文件,输出文件名
System.out.println("文件:" + fileOrDir.getName());
} else if (fileOrDir.isDirectory()) {
// 如果是目录,递归遍历子目录
System.out.println("目录:" + fileOrDir.getName());
testTraverseDirectory(fileOrDir);
}
}
}
2. 绝对路径与相对路径
- 绝对路径:从文件系统的根目录开始的完整路径。
- 相对路径:相对于当前工作目录的路径。
// 绝对路径示例
File absoluteFile = new File("/Users/username/example/test.txt");
System.out.println("绝对路径:" + absoluteFile.getAbsolutePath());
// 相对路径示例
File relativeFile = new File("example/test.txt");
System.out.println("相对路径:" + relativeFile.getPath());
3. RandomAccessFile
类
RandomAccessFile
是 Java 中一个非常特殊的类,它既可以用来读取文件,也可以用来写入文件。与其他 IO 类(如 FileInputStream
和 FileOutputStream
)不同,RandomAccessFile
允许您跳转到文件的任何位置,从那里开始读取或写入。这使得它特别适用于需要在文件中随机访问数据的场景,如数据库系统。
3.1 构造方法
RandomAccessFile
主要有两个构造方法:
RandomAccessFile(File file, String mode)
:使用给定的文件对象和访问模式创建RandomAccessFile
实例。RandomAccessFile(String name, String mode)
:使用给定的文件名和访问模式创建RandomAccessFile
实例。
访问模式 mode
的值可以是:
"r"
:以只读模式打开文件。"rw"
:以读写模式打开文件。"rws"
:以读写模式打开文件,并要求对内容或元数据的每个更新都被立即写入到底层存储设备。"rwd"
:与"rws"
类似,但仅要求对文件内容的更新被立即写入。
3.2 主要方法
getFilePointer()
:返回文件指针的当前位置。length()
:返回文件的长度。seek(long pos)
:将文件指针设置到文件中的pos
位置。read()
、read(byte[] b)
、readUTF()
:读取文件内容。write(byte[] b)
、write(int b)
、writeUTF(String str)
:写入文件内容。
/**
* RandomAccessFile
*/
private static void testRandomAccessFile() {
String filePath = "JavaSE/resourses/itwanger.txt";
try {
// 使用 RandomAccessFile 写入文件
writeToFile(filePath, "Hello, 沉默王二!");
// 使用 RandomAccessFile 读取文件
String content = readFromFile(filePath);
System.out.println("文件内容: " + content);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 使用 RandomAccessFile 写入文件
* @param filePath
* @param content
* @throws IOException
*/
private static void writeToFile(String filePath, String content) throws IOException {
try (RandomAccessFile randomAccessFile = new RandomAccessFile(filePath, "rw")) {
// 将文件指针移动到文件末尾(在此处追加内容)
randomAccessFile.seek(randomAccessFile.length());
// 写入内容
randomAccessFile.writeUTF(content);
}
}
/**
* 使用 RandomAccessFile 读取文件
* @param filePath
* @return
* @throws IOException
*/
private static String readFromFile(String filePath) throws IOException {
StringBuilder content = new StringBuilder();
try (RandomAccessFile randomAccessFile = new RandomAccessFile(filePath, "r")) {
// 将文件指针移动到文件开始处(从头开始读取)
randomAccessFile.seek(0);
content.append(randomAccessFile.readUTF());
}
return content.toString();
}
/**
* RandomAccessFile
*/
private static void testRandomAccessFile2() {
File file = new File("JavaSE/resourses/itwanger.txt");
try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
// 写入文件
raf.writeUTF("Hello, 沉默王二!");
// 将文件指针移动到文件开头
raf.seek(0);
// 读取文件内容
String content = raf.readUTF();
System.out.println("内容: " + content);
} catch (IOException e) {
e.printStackTrace();
}
}
4. Apache Commons IO 的 FileUtils
类
FileUtils
类是 Apache Commons IO 库中的一个类,提供了一些更为方便的方法来操作文件或目录。
- 复制文件或目录:
File srcFile = new File("path/to/src/file");
File destFile = new File("path/to/dest/file");
FileUtils.copyFile(srcFile, destFile);
FileUtils.copyDirectory(srcFile, destFile);
- 删除文件或目录:
File file = new File("path/to/file");
FileUtils.delete(file);
- 移动文件或目录:
File srcFile = new File("path/to/src/file");
File destFile = new File("path/to/dest/file");
FileUtils.moveFile(srcFile, destFile);
- 查询文件或目录的信息:
File file = new File("path/to/file");
Date modifyTime = FileUtils.lastModified(file);
long size = FileUtils.sizeOf(file);
String extension = FileUtils.getExtension(file.getName());
5. Hutool 的 FileUtil
类
FileUtil
类是 Hutool 工具包中的文件操作工具类,提供了一系列简单易用的文件操作方法。
- 复制文件:
File dest = FileUtil.file("FileUtilDemo2.java");
FileUtil.copyFile(file, dest);
- 移动文件或目录:
FileUtil.move(file, dest, true);
- 删除文件或目录:
FileUtil.del(file);
- 重命名文件或目录:
FileUtil.rename(file, "FileUtilDemo3.java", true);
- 读取文件的每一行数据:
FileUtil.readLines(file, "UTF-8").forEach(System.out::println);
6 思维导图
7 参考链接
Java File:IO 流的起点与终点