1. 引言
在 Java 编程中,文件和目录的操作是日常开发不可或缺的一部分。java.io.File类作为 Java 标准库中最早提供的文件抽象,提供了对文件和目录路径名的表示,以及创建、删除、重命名、查询属性等基本操作。虽然 Java 7 引入了java.nio.file.Path和Files等更现代的 API,但File类因其简单易用,至今仍被广泛使用。本文将全面介绍File类的核心用法,帮助你掌握 Java 文件操作的基础。
2. File 类概述
File类位于java.io包中,它不是文件本身,而是文件或目录路径名的抽象表示。一个File对象可以指向一个文件、一个目录,甚至是一个尚不存在的路径。
2.1 构造方法
File类提供了多种构造方式:
// 通过路径名字符串创建Filefile1=newFile("/home/user/test.txt");// 通过父路径和子路径字符串创建Filefile2=newFile("/home/user","test.txt");// 通过父 File 对象和子路径字符串创建FileparentDir=newFile("/home/user");Filefile3=newFile(parentDir,"test.txt");// 通过 URI 创建Filefile4=newFile(newURI("file:///home/user/test.txt"));2.2 路径分隔符
Java 中路径分隔符与操作系统相关,推荐使用常量:
// 路径分隔符(Windows 为 ;,Linux/macOS 为 :)StringpathSeparator=File.pathSeparator;// 名称分隔符(Windows 为 \,Linux/macOS 为 /)Stringseparator=File.separator;// 推荐使用跨平台写法Filefile=newFile("data"+File.separator+"config.properties");3. 文件属性查询
File类提供了丰富的方法来获取文件或目录的元信息。
3.1 基本属性
Filefile=newFile("example.txt");// 文件名Stringname=file.getName();// "example.txt"// 绝对路径StringabsPath=file.getAbsolutePath();// "/home/user/example.txt"// 父路径Stringparent=file.getParent();// "/home/user"// 文件大小(字节)longlength=file.length();// 最后修改时间(毫秒时间戳)longlastModified=file.lastModified();3.2 状态判断
booleanexists=file.exists();// 文件或目录是否存在booleanisFile=file.isFile();// 是否为文件booleanisDir=file.isDirectory();// 是否为目录booleanisHidden=file.isHidden();// 是否隐藏booleancanRead=file.canRead();// 是否可读booleancanWrite=file.canWrite();// 是否可写booleancanExecute=file.canExecute();// 是否可执行4. 文件与目录操作
4.1 创建与删除
Filefile=newFile("newFile.txt");// 创建新文件(返回 true 表示创建成功)booleancreated=file.createNewFile();// 删除文件或空目录booleandeleted=file.delete();// JVM 退出时自动删除(适用于临时文件)file.deleteOnExit();// 创建单级目录Filedir=newFile("myDir");booleandirCreated=dir.mkdir();// 创建多级目录(包括所有不存在的父目录)FilemultiDir=newFile("a/b/c/d");booleanmultiCreated=multiDir.mkdirs();4.2 重命名与移动
Filesource=newFile("old.txt");Filetarget=newFile("new.txt");// 重命名/移动(在同一文件系统内)booleanrenamed=source.renameTo(target);注意:
renameTo的行为依赖于平台,跨文件系统移动时可能失败。推荐使用Files.move()进行可靠的移动操作。
4.3 临时文件
// 创建临时文件(默认目录为系统临时目录)FiletempFile=File.createTempFile("prefix",".tmp");// 指定临时文件目录FiletempDir=newFile("/tmp/myapp");FiletempFile2=File.createTempFile("log",".txt",tempDir);// 临时文件通常配合 deleteOnExit 使用tempFile.deleteOnExit();5. 目录遍历
5.1 列出子项
Filedir=newFile("/home/user");// 列出所有子文件/目录名String[]names=dir.list();// 列出所有子 File 对象File[]files=dir.listFiles();// 使用文件名过滤器File[]txtFiles=dir.listFiles(newFilenameFilter(){@Overridepublicbooleanaccept(Filedir,Stringname){returnname.endsWith(".txt");}});// 使用 FileFilter(Java 8 Lambda 写法)File[]largeFiles=dir.listFiles(f->f.isFile()&&f.length()>1024*1024);5.2 递归遍历目录树
publicstaticvoidlistAllFiles(Filedir,Stringindent){File[]files=dir.listFiles();if(files==null)return;for(Filefile:files){System.out.println(indent+file.getName());if(file.isDirectory()){listAllFiles(file,indent+" ");}}}// 调用listAllFiles(newFile("/home/user"),"");6. 文件路径操作
6.1 相对路径与绝对路径
Filerelative=newFile("docs/readme.txt");System.out.println(relative.getPath());// "docs/readme.txt"System.out.println(relative.getAbsolutePath());// "/current/working/dir/docs/readme.txt"// 获取规范路径(解析 . 和 ..)Filecanonical=relative.getCanonicalFile();System.out.println(canonical.getPath());// 解析后的绝对路径6.2 路径转换
// File 转 URIURIuri=file.toURI();// File 转 Path(Java 7+)Pathpath=file.toPath();// 获取文件系统根目录File[]roots=File.listRoots();// Windows 返回 C:\, D:\ 等;Linux 返回 /7. 实战示例:文件工具类
下面是一个实用的文件操作工具类,整合了常用功能:
importjava.io.*;publicclassFileUtils{/** 递归删除文件或目录 */publicstaticbooleandeleteRecursively(Filefile){if(file.isDirectory()){File[]children=file.listFiles();if(children!=null){for(Filechild:children){deleteRecursively(child);}}}returnfile.delete();}/** 复制文件(字节流方式) */publicstaticvoidcopyFile(Filesource,Filedest)throwsIOException{try(InputStreamin=newFileInputStream(source);OutputStreamout=newFileOutputStream(dest)){byte[]buffer=newbyte[8192];intlen;while((len=in.read(buffer))!=-1){out.write(buffer,0,len);}}}/** 获取文件扩展名 */publicstaticStringgetExtension(Filefile){Stringname=file.getName();intdotIndex=name.lastIndexOf('.');return(dotIndex==-1)?"":name.substring(dotIndex+1);}/** 获取文件大小(可读格式) */publicstaticStringformatSize(longbytes){String[]units={"B","KB","MB","GB","TB"};intunitIndex=0;doublesize=bytes;while(size>=1024&&unitIndex<units.length-1){size/=1024;unitIndex++;}returnString.format("%.2f %s",size,units[unitIndex]);}}8. File 类的局限与替代方案
虽然File类简单易用,但它存在一些局限性:
| 局限 | 说明 | 替代方案 |
|---|---|---|
| 不支持符号链接处理 | 无法区分符号链接与真实文件 | java.nio.file.Files |
| 元数据操作有限 | 无法设置文件权限、所有者等 | Files.setPosixFilePermissions() |
| 不支持文件监视 | 无法监听文件变化事件 | java.nio.file.WatchService |
| 异常处理不完善 | 失败时返回 boolean,不抛异常 | Files方法抛出IOException |
| 不支持文件属性批量读取 | 每次查询都需系统调用 | Files.readAttributes() |
对于新项目,建议优先考虑java.nio.file包下的Path、Paths和Files类,它们提供了更强大、更可靠的文件操作能力。
9. 总结
java.io.File类是 Java 文件操作的基础,掌握它的核心方法对于日常开发至关重要。本文从构造方法、属性查询、创建删除、目录遍历到实战工具类,全面覆盖了File的常见用法。虽然File类在新项目中逐渐被NIO.2API 取代,但理解它仍然是学习 Java I/O 体系的重要一步。建议你在实际开发中根据需求选择合适的 API,在简单场景下File类依然是一个轻量高效的选择。