Java处理Excel文件执行移动操作时抛出java.nio.file.FileSystemException异常
问题修复方案
错误根因
你的代码执行顺序有问题:你先通过new FileInputStream(file)打开了目标Excel文件的输入流,此时该文件已经被当前Java进程持有锁,后续再调用Files.move移动文件时,就会触发文件被其他进程占用的报错。
你之前只做入库逻辑没问题,是因为不需要移动文件,不存在操作被文件锁拦截的场景。
修复方案
调整操作顺序即可,这里推荐两种可行方案:
方案一:先完成文件读取、入库全流程,关闭流后再移动文件
使用try-with-resources自动管理流资源,避免手动关流遗漏导致的资源泄漏,修正后的代码如下:
public static void acceptExcellFileAndInsertToDatabase(File file) { String phoneNumber = ""; String textMessage = ""; // 用try-with-resources自动关流,执行完括号内逻辑后会自动释放文件占用 try (FileInputStream excelFile = new FileInputStream(file)) { Workbook workbook = new XSSFWorkbook(excelFile); Sheet datatypeSheet = workbook.getSheetAt(0); Iterator<Row> iterator = datatypeSheet.iterator(); while (iterator.hasNext()) { Row currentRow = iterator.next(); Iterator<Cell> cellIterator = currentRow.iterator(); while (cellIterator.hasNext()) { Cell currentCell = cellIterator.next(); if (currentCell.getCellTypeEnum() == CellType.NUMERIC) { phoneNumber = NumberToTextConverter.toText(currentCell.getNumericCellValue()); } else if (currentCell.getCellTypeEnum() == CellType.STRING) { textMessage = String.valueOf(currentCell.getStringCellValue()); } } } insertExcellFileToDb(phoneNumber, textMessage); System.out.println(phoneNumber + " " + textMessage); // 流已经自动关闭,文件占用释放,此时再移动文件 Path sourcePath = Paths.get(String.valueOf(file)); Path targetPath = Paths.get("C:\\Users\\anar.memmedov\\Desktop\\ko\\" + sourcePath.getFileName()); Files.move(sourcePath, targetPath); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
方案二:先移动文件,再读取移动后的文件做入库操作
如果你的业务要求优先归档文件,就可以先移动文件,再从目标路径读取文件处理:
public static void acceptExcellFileAndInsertToDatabase(File file) { try { String phoneNumber = ""; String textMessage = ""; Path sourcePath = Paths.get(String.valueOf(file)); Path targetPath = Paths.get("C:\\Users\\anar.memmedov\\Desktop\\ko\\" + sourcePath.getFileName()); // 先移动文件,此时还没打开文件,不存在占用 Files.move(sourcePath, targetPath); // 读取移动后的目标路径的文件 try (FileInputStream excelFile = new FileInputStream(targetPath.toFile())) { Workbook workbook = new XSSFWorkbook(excelFile); Sheet datatypeSheet = workbook.getSheetAt(0); Iterator<Row> iterator = datatypeSheet.iterator(); while (iterator.hasNext()) { Row currentRow = iterator.next(); Iterator<Cell> cellIterator = currentRow.iterator(); while (cellIterator.hasNext()) { Cell currentCell = cellIterator.next(); if (currentCell.getCellTypeEnum() == CellType.NUMERIC) { phoneNumber = NumberToTextConverter.toText(currentCell.getNumericCellValue()); } else if (currentCell.getCellTypeEnum() == CellType.STRING) { textMessage = String.valueOf(currentCell.getStringCellValue()); } } } insertExcellFileToDb(phoneNumber, textMessage); System.out.println(phoneNumber + " " + textMessage); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
额外说明
该问题本质是单进程内的资源占用顺序问题,使用多线程完全解决不了,反而会增加不必要的复杂度,不需要做这方面的尝试。
内容的提问来源于stack exchange,提问作者iwritecomeinmymind
相关产品推荐
相关产品推荐

