使用JavaCV生成AVI转MP4后,删除冗余AVI报FileSystemException求助
我用JavaCV创建并录制AVI格式的视频文件,之后通过Jaffree将其转换为MP4格式。但当尝试删除已冗余的AVI文件时,抛出了FileSystemException异常。我已经释放了所有持有该文件的对象,同时也尝试使用Apache Commons IO的FileUtils.forceDelete(sample.getFile())强制删除,问题依旧存在。相关代码类定义如下:
public class PacketRecorderTest { private static final DateFormat DATE_FORMAT =... // 其他相关代码 }
我之前处理过好几起类似的跨库文件操作后无法删除的问题,大概率是文件句柄没有被完全释放——尤其是Jaffree调用外部FFmpeg进程的场景,很容易出现这种情况。下面给你几个针对性的排查和解决方向:
1. 确保Jaffree转码资源彻底释放
Jaffree转码时会启动外部FFmpeg进程,如果这个进程没正常退出,或者相关的流/对象没关闭,就会死死占用AVI文件。你得注意这几点:
- 如果用了异步转码,一定要通过
Future.get()等方式等待转码任务完全执行完毕,再去删文件; - 用try-with-resources语法管理Jaffree的转码对象(比如
Transcoder),让它自动释放资源:
try (Transcoder transcoder = Transcoder.create() .addInput(aviFile.getAbsolutePath()) .addOutput(mp4FilePath) .build()) { transcoder.execute(); } // 转码彻底完成后再执行删除操作
2. 再仔细检查JavaCV的Recorder释放逻辑
虽然你说已经释放了对象,但要确保FrameRecorder的release()方法被正确调用,而且没有遗漏的引用(比如静态变量、全局集合还攥着Recorder实例):
FrameRecorder recorder = FrameRecorder.createDefault(aviFile, width, height); try { recorder.start(); // 你的录制逻辑 } finally { if (recorder != null) { recorder.stop(); recorder.release(); // 这一步必须有,确保释放文件句柄 } }
3. 给文件释放加一点延迟
有时候外部进程(比如FFmpeg)退出后,操作系统需要一点时间才能完全释放文件句柄,尤其是Windows系统。不妨试试在转码完成后延迟1-2秒再删除:
try { Thread.sleep(1000); // 延迟1秒,可根据实际情况调整时长 FileUtils.forceDelete(aviFile); } catch (InterruptedException | IOException e) { e.printStackTrace(); }
4. 捕获异常看详细占用信息
FileSystemException通常会告诉你哪个进程在占用文件,你可以打印完整的异常堆栈,定位问题根源:
try { FileUtils.forceDelete(aviFile); } catch (FileSystemException e) { System.err.println("文件被占用的详细信息:" + e.getMessage()); e.printStackTrace(); }
比如Windows系统的异常会显示进程ID,你可以用任务管理器查对应的进程是不是FFmpeg或者你的Java进程。
5. 试试NIO的文件删除方式
有时候Apache Commons IO的删除方法处理特殊情况不如NIO灵活,你可以换用Java NIO的API试试:
try { Files.deleteIfExists(aviFile.toPath()); } catch (IOException e) { e.printStackTrace(); }
6. 排查是否有其他代码在占用文件
比如有没有其他线程在读取这个AVI文件?或者日志、监控类的代码在偷偷占用?你可以梳理整个代码流程中对该文件的所有操作,确保没有遗漏的输入流/输出流没关闭。
内容的提问来源于stack exchange,提问作者imvinaypatil

