当前位置: 首页 > news >正文

Java NIO Files 类

Java NIOFiles类详细学习笔记

1. 概述

java.nio.file.Files是 Java NIO.2 (Java 7 引入) 中的核心工具类。它提供了一系列静态方法,用于操作文件、目录和符号链接。

核心特点:

  • 工具类:所有方法都是静态的,无需实例化。
  • 基于Path:操作对象是Path接口,而非传统的File类。
  • 原子性与异常处理:许多操作是原子的,且抛出受检异常(如IOException),强制开发者处理错误。
  • 流式处理:支持将文件内容作为Stream处理,便于函数式编程。
  • 替代方案:它极大地简化了传统java.io中繁琐的代码(如手动创建目录、复制文件流等)。

注意Files类的方法通常会在底层调用操作系统原生的系统调用,因此在处理大文件时,性能通常优于传统的FileInputStream/FileOutputStream组合,但具体取决于操作类型。


2. 核心功能详解

2.1 文件基本操作

2.1.1 创建文件
// 创建新文件,如果文件已存在则抛出 FileAlreadyExistsExceptionPathpath=Paths.get("example.txt");Files.createFile(path);// 创建新文件,如果已存在则覆盖(不推荐用于生产环境,除非明确意图)Files.write(path,"Hello".getBytes(),StandardOpenOption.CREATE,StandardOpenOption.TRUNCATE_EXISTING);// 创建目录(如果父目录不存在则抛出异常)Files.createDirectory(Paths.get("dir/subdir"));// 创建目录(如果父目录不存在,则递归创建,类似 mkdirs)Files.createDirectories(Paths.get("dir/subdir"));
2.1.2 删除文件
// 删除文件,如果不存在则抛出 NoSuchFileExceptionFiles.delete(path);// 删除文件,如果不存在则不抛出异常(静默删除)Files.deleteIfExists(path);
2.1.3 移动与重命名
// 移动文件(重命名)Pathsource=Paths.get("old.txt");Pathtarget=Paths.get("new.txt");// 基本移动Files.move(source,target);// 移动并覆盖目标(如果目标存在)Files.move(source,target,StandardCopyOption.REPLACE_EXISTING);// 原子移动(如果文件系统支持,保证移动操作的原子性)Files.move(source,target,StandardCopyOption.ATOMIC_MOVE);
2.1.4 复制文件
Pathsource=Paths.get("source.txt");Pathtarget=Paths.get("dest.txt");// 基本复制Files.copy(source,target);// 复制并覆盖Files.copy(source,target,StandardCopyOption.REPLACE_EXISTING);// 复制时保留属性Files.copy(source,target,StandardCopyOption.COPY_ATTRIBUTES);

2.2 文件内容读写

Files类提供了极其便捷的读写方法,适合中小文件。对于超大文件,建议使用InputStream/OutputStreamStream

2.2.1 读取文件
Pathpath=Paths.get("data.txt");// 读取所有字节byte[]bytes=Files.readAllBytes(path);// 读取所有行(返回 List<String>)List<String>lines=Files.readAllLines(path,StandardCharsets.UTF_8);// 使用 Stream 逐行读取(适合大文件,惰性加载)try(Stream<String>stream=Files.lines(path,StandardCharsets.UTF_8)){stream.filter(line->line.contains("error")).forEach(System.out::println);}
2.2.2 写入文件
Pathpath=Paths.get("output.txt");List<String>lines=Arrays.asList("Line 1","Line 2","Line 3");// 写入所有行(覆盖模式)Files.write(path,lines,StandardCharsets.UTF_8);// 追加模式Files.write(path,Arrays.asList("New Line"),StandardCharsets.UTF_8,StandardOpenOption.APPEND);// 写入字节Files.write(path,"Hello World".getBytes(StandardCharsets.UTF_8));

2.3 文件属性与元数据

2.3.1 获取基本属性
Pathpath=Paths.get("example.txt");// 文件大小longsize=Files.size(path);// 最后修改时间FileTimelastModified=Files.getLastModifiedTime(path);// 最后访问时间FileTimelastAccess=Files.getLastAccessTime(path);// 创建时间(取决于文件系统支持)FileTimecreateTime=Files.getAttribute(path,"creationTime");// 判断是否为目录、文件、符号链接booleanisDir=Files.isDirectory(path);booleanisFile=Files.isRegularFile(path);booleanisLink=Files.isSymbolicLink(path);booleanexists=Files.exists(path);booleanreadable=Files.isReadable(path);booleanwritable=Files.isWritable(path);
2.3.2 获取自定义属性
// 获取特定属性Objectattr=Files.getAttribute(path,"basic:permission");// 设置属性Files.setAttribute(path,"basic:readonly",true);
2.3.3 文件权限 (POSIX 系统)
// 检查权限booleancanExecute=Files.isExecutable(path);// 设置权限 (需要导入 java.nio.file.attribute.PosixFilePermission)if(Files.getFileStore(path).supportsFileAttributeView(PosixFileAttributeView.class)){Set<PosixFilePermission>perms=Files.getPosixFilePermissions(path);perms.add(PosixFilePermission.OWNER_EXECUTE);Files.setPosixFilePermissions(path,perms);}

2.4 目录遍历

2.4.1 列出目录内容
Pathdir=Paths.get(".");// 获取目录下的文件流try(Stream<Path>stream=Files.list(dir)){stream.forEach(System.out::println);}// 递归遍历目录try(Stream<Path>stream=Files.walk(dir)){stream.filter(Files::isRegularFile).forEach(System.out::println);}
2.4.2 搜索文件
Pathdir=Paths.get(".");// 搜索匹配特定条件的文件try(Stream<Path>stream=Files.find(dir,10,// 最大深度(path,attr)->path.toString().endsWith(".java")&&Files.isRegularFile(path))){stream.forEach(System.out::println);}// 搜索匹配特定模式的文件 (glob)try(Stream<Path>stream=Files.newDirectoryStream(dir,"*.txt")){stream.forEach(System.out::println);}

2.5 链接与临时文件

2.5.1 符号链接
Pathtarget=Paths.get("target.txt");Pathlink=Paths.get("link.txt");// 创建符号链接Files.createSymbolicLink(link,target);// 读取符号链接指向的目标PathrealPath=Files.readSymbolicLink(link);// 解析符号链接(获取最终目标)Pathresolved=Files.readAllLinks(target);// 注意:Files 没有直接 readAllLinks,通常用 resolveSymbolicLinks 或手动遍历
2.5.2 临时文件与目录
// 创建临时文件PathtempFile=Files.createTempFile("myApp",".tmp");// 创建临时目录PathtempDir=Files.createTempDirectory("myApp");// 在系统默认临时目录创建PathtempFile2=Files.createTempFile(null,".log");// 设置临时文件删除策略(JDK 7+ 支持)tempFile.toFile().deleteOnExit();// 传统方式// 或者使用 Files 的 deleteOnExit 包装(需手动管理)

2.6 文件系统与路径

// 获取文件所在的文件系统FileSystemfs=path.getFileSystem();// 获取文件存储信息FileStorestore=Files.getFileStore(path);System.out.println("Total Space: "+store.getTotalSpace());System.out.println("Usable Space: "+store.getUsableSpace());// 检查文件系统是否支持某些特性booleansupportsLinks=store.supportsFileAttributeView(LinkAttributeView.class);

3. 最佳实践与注意事项

3.1 异常处理

Files类的方法大多抛出IOException

  • 推荐:使用try-with-resources语句自动关闭资源(如Stream)。
  • 注意:区分FileAlreadyExistsException,NoSuchFileException,AccessDeniedException等具体异常类型,以便进行更精细的错误处理。

3.2 性能考量

  • 小文件readAllBytesreadAllLines非常便捷且性能良好。
  • 大文件:避免使用readAllBytes,应使用InputStreamFiles.lines()流式处理,防止内存溢出 (OOM)。
  • 大量文件遍历:使用Files.walk()Files.find()配合流式处理,避免一次性加载所有路径到内存。

3.3 编码问题

  • 读写文本文件时,务必指定字符集(如StandardCharsets.UTF_8),避免依赖平台默认编码导致乱码。

3.4 原子性

  • 在并发环境中,Files.moveFiles.copy的原子性取决于底层文件系统。
  • 对于关键操作,建议使用StandardCopyOption.ATOMIC_MOVE,但这要求目标路径所在的文件系统支持原子移动。

3.5 权限与安全

  • 操作文件前,建议先检查isReadable,isWritable等权限。
  • 创建临时文件时,注意设置合适的权限,防止敏感信息泄露。

4. 代码示例:综合应用

以下是一个综合示例,演示了如何创建一个目录结构、写入文件、读取内容、遍历目录并统计文件数量。

importjava.io.IOException;importjava.nio.file.*;importjava.nio.charset.StandardCharsets;importjava.util.List;importjava.util.stream.Stream;publicclassFilesDemo{publicstaticvoidmain(String[]args){PathbaseDir=Paths.get("demo_project");PathsrcDir=baseDir.resolve("src");Pathfile1=srcDir.resolve("Main.java");Pathfile2=srcDir.resolve("Utils.java");try{// 1. 创建目录结构 (递归)Files.createDirectories(srcDir);System.out.println("目录创建成功: "+srcDir);// 2. 写入文件List<String>content1=List.of("public class Main {"," public static void main(String[] args) {}","}");Files.write(file1,content1,StandardCharsets.UTF_8);Files.write(file2,List.of("class Utils { }"),StandardCharsets.UTF_8);System.out.println("文件写入成功");// 3. 读取文件内容List<String>lines=Files.readAllLines(file1,StandardCharsets.UTF_8);System.out.println("读取文件内容:");lines.forEach(System.out::println);// 4. 遍历目录并统计longcount=0;try(Stream<Path>stream=Files.walk(srcDir)){count=stream.filter(Files::isRegularFile).filter(p->p.toString().endsWith(".java")).count();}System.out.println("Java 文件数量: "+count);// 5. 获取文件属性System.out.println("文件大小: "+Files.size(file1)+" bytes");System.out.println("最后修改时间: "+Files.getLastModifiedTime(file1));// 6. 移动文件Pathbackup=baseDir.resolve("backup").resolve("Main.java.bak");Files.createDirectories(backup.getParent());Files.move(file1,backup,StandardCopyOption.REPLACE_EXISTING);System.out.println("文件已移动至备份目录");// 7. 删除文件Files.deleteIfExists(file2);System.out.println("文件 Utils.java 已删除");}catch(IOExceptione){e.printStackTrace();}}}

5. 总结

java.nio.file.Files类是 Java 文件操作的现代标准。它提供了:

  • 简洁的 API:一行代码完成复杂的文件操作。
  • 强大的功能:支持流式处理、属性操作、目录遍历等。
  • 更好的异常处理:明确的异常类型,便于调试。
  • 跨平台兼容性:基于Path接口,屏蔽了不同操作系统的差异。

掌握Files类,能够显著提升 Java 应用程序在文件处理方面的开发效率和代码质量。在实际开发中,应优先使用Files类替代传统的java.io文件操作方式。

http://www.jsqmd.com/news/604452/

相关文章:

  • 2026实测|6款主流PPT生成软件横评,打工人再也不用熬到深夜做PPT - 品牌测评鉴赏家
  • WithClock 桌面时钟,极致轻量化,鼠标穿透无打扰,自定义皮肤,双模式时钟,打造沉浸式桌面时间体验
  • Swagger中常用注解
  • 基于FPGA XDMA中断与双缓存架构的PCIE 3.0性能实测与优化
  • python sendgrid
  • 2026年AI PPT工具大揭秘,轻松解锁高效创作 - 品牌测评鉴赏家
  • 视频批量裁剪助手 - 支持 AVI、MKV 等多格式批量处理,精准设置裁剪时间
  • 【企业级MCP微服务基座】:基于FastAPI+Pydantic+Structured Logging的Python模板,已通过金融级压测(QPS 12,800+)
  • 滑模控制、反步控制、传统PID四旋翼无人机轨迹跟踪控制仿真
  • Taskwarrior钩子脚本开发终极指南:如何扩展你的任务管理功能
  • 如何用抖音下载器实现内容创作效率提升300%?一个开源工具的全方位指南
  • 硬字幕去除难题终结者:AI驱动的Video-subtitle-remover如何重新定义视频修复
  • D3作业1-K8s 存储与服务实验手册(实验1-4)
  • 智能保险箱WiFi配网总失败?保姆级排查指南(附双频路由器设置)
  • 博主实测|5款PPT生成网站,告别熬夜抠图,新手也能一键出片 - 品牌测评鉴赏家
  • 分布式一致性动态事件触发+线性多智能体系统仿真(复现参考文献)Matlab实现
  • 告别混乱依赖!用Melos管理Flutter多包项目的5个关键技巧
  • WebRTC+FFmpeg实战:如何用C++开发一个低延迟视频会议Demo?
  • 揭秘蒸发冷省电空调,成车间降温设备优选
  • 6个宝藏PPT模板网站,告别熬夜改稿,小白也能出质感大片 - 品牌测评鉴赏家
  • 基于串口(COM 口)同一时刻只能访问一次的独占特性,结合上文讨论的串口事件驱动编程、异步操作、读写锁和线程同步,本节将重点探讨如何优化串口事件驱动的性能和鲁棒性
  • 终极PoWFaucet会话管理完整指南:从启动到完成的6个关键步骤
  • AI博主实测3款PPT一键制作工具|告别熬夜排版,新手也能秒出大片 - 品牌测评鉴赏家
  • 手把手教你用Cherry Studio搭建一个‘全栈’AI助手:从聊天、翻译到文生图
  • 用树莓派Pico和电位计式传感器,5分钟做个简易角度测量仪(附完整Python代码)
  • IDM无限试用完全指南:突破30天限制的技术实现方案
  • 终极指南:Retrieval-based-Voice-Conversion-WebUI扩展开发与自定义模块设计
  • 江苏南通车间降温,蒸发冷省电空调凭优势脱颖而出
  • uosc性能优化实战:解决UI卡顿与渲染延迟问题终极指南
  • 5步掌握B站资源高效下载:BiliTools终极使用指南