You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Java移动文件时出现「文件被其他进程占用」错误?

问题:使用Java Files.move()移动文件时提示文件被占用错误

在实现文件大小超限后移动到新目录的功能时,调用Files.move()抛出以下错误:

Exception in thread "main" java.nio.file.FileSystemException: C:\Users\Public\Operational_Functional_Block\src\obf_reg.docx -> C:\Users\Public\Operational_Functional_Block\src\FullFolders\obf.reg[Full].docx:
The process cannot access the file because it is being used by another process

异常栈信息:

java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:92)
java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
java.base/sun.nio.fs.WindowsFileCopy.move(WindowsFileCopy.java:403)
java.base/sun.nio.fs.WindowsFileSystemProvider.move(WindowsFileSystemProvider.java:293)
java.base/java.nio.file.Files.move(Files.java:1432)
com.example.demo.Tester.main(Tester.java:44)

使用Apache POI开发的测试代码如下:

package com.example.demo;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xwpf.usermodel.*;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

public class Tester {
    public static void main(String[] args) throws IOException {
        ZipSecureFile.setMinInflateRatio(0.001);
        File pathn1 = new File("C:\\Users\\Public\\Operational_Functional_Block\\src\\obf_reg.docx");
        if (!(new File(String.valueOf(pathn1)).exists())) {
            XWPFDocument docx12 = new XWPFDocument();
            XWPFParagraph par1 = docx12.createParagraph();
            XWPFRun run1 = par1.createRun();
            run1.setText("...---...");
            run1.addBreak();
            try (FileOutputStream out1 = new FileOutputStream(String.valueOf(pathn1))) {
                docx12.write(out1);
                out1.close();
                docx12.close();
            }
        }
        String repeatCommand = "whatever";
        while (!repeatCommand.equals("N")) {
            Path path = Paths.get(String.valueOf(pathn1));
            if (Files.size(path) < 2350) {
                System.out.println("size" + "------>" + Files.size(path));
            } else {
                File logM = new File("C:\\Users\\Public\\Operational_Functional_Block\\src\\FullFolders");
                logM.mkdir();
                // ------------------------------
                File pathn2 = new File("C:\\Users\\Public\\Operational_Functional_Block\\src\\obf_reg.docx");
                //File pathn3 = new File("C:\\Users\\Public\\Operational_Functional_Block\\src\\obf_reg[Full].docx");
                //pathn2.renameTo(pathn3);
                // ------------------------------
                Path normPF = Paths.get(String.valueOf(pathn2));
                Path logPF = Paths.get("C:\\Users\\Public\\Operational_Functional_Block\\src\\FullFolders\\obf.reg[Full].docx");
                Files.move(normPF, logPF, REPLACE_EXISTING);
                // ------------------------------
                File file1 = new File("C:\\Users\\Public\\Operational_Functional_Block\\src\\obf_reg.docx");
                file1.createNewFile();
                // ------------------------------
                XWPFDocument docx1 = new XWPFDocument();
                XWPFParagraph par21 = docx1.createParagraph();
                XWPFRun run21 = par21.createRun();
                run21.setText("...---...");
                run21.addBreak();
                try (FileOutputStream out1 = new FileOutputStream(String.valueOf(pathn1))) {
                    docx1.write(out1);
                    out1.close();
                    docx1.close();
                }
            }
            XWPFDocument docx = new XWPFDocument();
            if (new File(String.valueOf(pathn1)).exists()) {
                docx = new XWPFDocument(new FileInputStream(String.valueOf(pathn1)));
            }
            XWPFParagraph par2 = docx.createParagraph();
            XWPFRun run2 = par2.createRun();
            run2.setText("...---...");
            run2.addBreak();
            try (FileOutputStream out = new FileOutputStream(String.valueOf(pathn1))) {
                docx.write(out);
            }
            System.out.println("did thing...");
        }
    }
}
解决方案

错误根源是文件资源未完全释放,Windows系统下文件被打开的流或POI文档对象占用时,无法执行移动操作。具体修复方式如下:

1. 核心修复:确保所有资源自动释放

所有涉及文件输入输出的流、以及XWPFDocument对象,都必须用try-with-resources包裹,确保资源在代码块结束后自动关闭,避免文件被持续占用。

2. 优化后的完整代码

package com.example.demo;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xwpf.usermodel.*;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

public class Tester {
    public static void main(String[] args) throws IOException {
        ZipSecureFile.setMinInflateRatio(0.001);
        File pathn1 = new File("C:\\Users\\Public\\Operational_Functional_Block\\src\\obf_reg.docx");
        
        // 初始化文件:用try-with-resources自动释放资源
        if (!pathn1.exists()) {
            try (XWPFDocument docx12 = new XWPFDocument();
                 FileOutputStream out1 = new FileOutputStream(pathn1)) {
                XWPFParagraph par1 = docx12.createParagraph();
                XWPFRun run1 = par1.createRun();
                run1.setText("...---...");
                run1.addBreak();
                docx12.write(out1);
            }
        }

        String repeatCommand = "whatever";
        while (!repeatCommand.equals("N")) {
            Path path = pathn1.toPath();
            if (Files.size(path) < 2350) {
                System.out.println("size" + "------>" + Files.size(path));
            } else {
                File logDir = new File("C:\\Users\\Public\\Operational_Functional_Block\\src\\FullFolders");
                if (!logDir.exists()) {
                    logDir.mkdirs(); // 用mkdirs确保父目录不存在时也能创建成功
                }

                Path normPF = pathn1.toPath();
                Path logPF = Paths.get("C:\\Users\\Public\\Operational_Functional_Block\\src\\FullFolders\\obf.reg[Full].docx");
                
                // 此时文件资源已全部释放,可以正常移动
                Files.move(normPF, logPF, REPLACE_EXISTING);

                // 重建新文件:继续用try-with-resources管理资源
                try (XWPFDocument docx1 = new XWPFDocument();
                     FileOutputStream out1 = new FileOutputStream(pathn1)) {
                    XWPFParagraph par21 = docx1.createParagraph();
                    XWPFRun run21 = par21.createRun();
                    run21.setText("...---...");
                    run21.addBreak();
                    docx1.write(out1);
                }
            }

            // 追加内容到文件:修复此处的资源泄漏问题
            try (FileInputStream in = new FileInputStream(pathn1);
                 XWPFDocument docx = new XWPFDocument(in);
                 FileOutputStream out = new FileOutputStream(pathn1)) {
                XWPFParagraph par2 = docx.createParagraph();
                XWPFRun run2 = par2.createRun();
                run2.setText("...---...");
                run2.addBreak();
                docx.write(out);
            }

            System.out.println("did thing...");
        }
    }
}

3. 额外优化点

  • 移除重复创建的File对象:直接使用已定义的pathn1,避免冗余代码
  • 替换mkdir()为mkdirs():确保目标目录的父目录不存在时也能成功创建
  • 删除手动close()调用:try-with-resources会自动处理资源关闭,手动调用可能引发重复关闭异常

内容的提问来源于stack exchange,提问作者Sofia_The_Launch_Technician

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 09:57:37