如何正确移动文件避免 NoSuchFileException 错误

发布时间 - 2026-02-02 00:00:00    点击率:

本文详解因重复调用 `files.move()` 导致 `nosuchfileexception` 的根本原因,并提供结构清晰、资源安全的文件分类移动方案,确保 csv 文件仅被移动一次且 filereader 正确自动关闭。

在使用 Java NIO 的 Files.move() 处理批量 CSV 文件时,出现 java.nio.file.NoSuchFileException 是一个典型逻辑错误——并非文件路径错误,而是同一文件被多次移动。从您提供的代码可见:内层 for (CsvLine item : beans) 循环中,一旦匹配到 item.getValue() 为 2/43/32,便立即执行一次 Files.move(..., invalid_files);但循环并未终止,后续迭代会再次尝试对已被移走的原始文件调用 Files.move(),从而触发 NoSuchFileException。

更严重的是,原代码中存在两处 br.close() 手动调用(分别在 invalid 和 processed 分支),而 FileReader 已被声明在 try-with-resources 中,手动关闭不仅冗余,还可能引发 IllegalStateException。

✅ 正确做法是:

  • 只移动一次文件:在解析完全部 CSV 行后,统一决定目标目录;
  • 利用 try-with-resources 自动管理资源:彻底移除所有手动 close();
  • 提前标记 + 统一移动:用 moveTo 变量动态指向 invalid_files 或 processed,最后单次执行 Files.move()。

以下是重构后的健壮实现:

@Override
public void execute(JobExecutionContext context) {
    File directoryPath = new File("C:\\csv\\nov");

    // 创建 processed 和 invalid_files 子目录(幂等)
    Path processedDir = Path.of(directoryPath.getAbsolutePath(), "processed");
    Path invalidDir = Path.of(directoryPath.getAbsolutePath(), "invalid_files");
    try {
        Files.createDirectories(processedDir);
        Files.createDirectories(invalidDir);
    } catch (IOException e) {
        throw new RuntimeException("Failed to create directories", e);
    }

    // 过滤 CSV 文件
    FilenameFilter csvFilter = (dir, name) -> name.toLowerCase().endsWith(".csv");
    File[] csvFiles = directoryPath.listFiles(csvFilter);
    if (csvFiles == null) {
        System.out.println("No CSV files found.");
        return;
    }

    for (File file : csvFiles) {
        Path originalPath = file.toPath();
        Path moveTo = processedDir.resolve(originalPath.getFileName()); // 默认移至 processed

        try (FileReader br = new FileReader(file, StandardCharsets.UTF_16)) {
            List beans = new CsvToBeanBuilder(br)
                    .withType(CsvLine.class)
                    .withSeparator('\t')
                    .withSkipLines(3)
                    .build()
                    .parse();

            // 检查任意一行是否含非法值 →

标记为 invalid for (CsvLine item : beans) { Integer value = item.getValue(); if (value != null && (value.equals(2) || value.equals(43) || value.equals(32))) { moveTo = invalidDir.resolve(originalPath.getFileName()); System.out.printf("⚠️ Invalid value %d found in %s → will move to invalid_files%n", value, file.getName()); break; // 关键:跳出循环,避免重复判断和移动 } } } catch (Exception e) { // 解析失败视为异常文件(如编码错误、格式损坏) System.err.printf("❌ Parsing failed for %s: %s%n", file.getName(), e.getMessage()); moveTo = invalidDir.resolve(originalPath.getFileName()); } // ✅ 统一、安全地执行移动(仅一次!) try { Files.move(originalPath, moveTo, StandardCopyOption.REPLACE_EXISTING); System.out.printf("✅ Moved %s → %s%n", originalPath.getFileName(), moveTo.getParent().getFileName()); } catch (IOException e) { throw new RuntimeException("Failed to move file: " + originalPath, e); } } }

? 关键改进说明

  • break 不可省略:确保发现首个非法值即退出循环,防止二次移动;
  • createDirectories() 替代 createDirectory():自动创建父目录(即使 invalid_files 上级不存在);
  • 空指针防护:item.getValue() 判空避免 NullPointerException;
  • 异常兜底策略:CSV 解析失败时也归入 invalid_files,提升鲁棒性;
  • 日志语义清晰:区分 ⚠️ Invalid value、❌ Parsing failed、✅ Moved,便于问题追踪。

? 额外建议

  • 生产环境应使用 SLF4J/Logback 替代 System.out;
  • 对大文件,可考虑流式校验(不全量加载 beans),进一步优化内存;
  • 移动前可先 Files.exists(originalPath) 双重校验(虽非必需,但增强防御性)。

遵循此模式,即可彻底规避 NoSuchFileException,实现安全、可维护的文件分类处理流程。


# java  # 编码  # csv  # ai  # logback  # nio  # for  # try  # break  # 循环  # 指针  # 空指针  # 重构  # 已被  # 的是  # 是一个  # 不存在  # 首个  # 不全  # 还可能  # 两处  # 移除  # 根本原因 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Java类加载基本过程详细介绍  JavaScript如何实现音频处理_Web Audio API如何工作?  昵图网官方站入口 昵图网素材图库官网入口  如何快速搭建高效可靠的建站解决方案?  大型企业网站制作流程,做网站需要注册公司吗?  Android自定义listview布局实现上拉加载下拉刷新功能  Laravel如何自定义错误页面(404, 500)?(代码示例)  浅谈javascript alert和confirm的美化  laravel怎么为应用开启和关闭维护模式_laravel应用维护模式开启与关闭方法  如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)  如何在Windows虚拟主机上快速搭建网站?  Laravel如何生成API文档?(Swagger/OpenAPI教程)  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  如何在服务器上配置二级域名建站?  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  如何自定义建站之星网站的导航菜单样式?  香港服务器租用费用高吗?如何避免常见误区?  Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】  DeepSeek是免费使用的吗 DeepSeek收费模式与Pro版本功能详解  北京企业网站设计制作公司,北京铁路集团官方网站?  Linux系统命令中tree命令详解  活动邀请函制作网站有哪些,活动邀请函文案?  node.js报错:Cannot find module 'ejs'的解决办法  大连网站制作公司哪家好一点,大连买房网站哪个好?  制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?  laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法  Laravel如何处理和验证JSON类型的数据库字段  Laravel怎么实现搜索高亮功能_Laravel结合Scout与Algolia全文检索【实战】  制作电商网页,电商供应链怎么做?  Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】  如何利用DOS批处理实现定时关机操作详解  javascript基本数据类型及类型检测常用方法小结  uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址  Laravel Session怎么存储_Laravel Session驱动配置详解  轻松掌握MySQL函数中的last_insert_id()  Laravel怎么解决跨域问题_Laravel配置CORS跨域访问  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析  大学网站设计制作软件有哪些,如何将网站制作成自己app?  如何批量查询域名的建站时间记录?  Laravel如何创建自定义Artisan命令?(代码示例)  Laravel如何创建和注册中间件_Laravel中间件编写与应用流程  通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】  如何在橙子建站上传落地页?操作指南详解  Python函数文档自动校验_规范解析【教程】  黑客如何通过漏洞一步步攻陷网站服务器?  HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】  如何快速查询域名建站关键信息?  Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理  Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】