如何避免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
相关产品推荐
相关产品推荐

