Java I/O:确保文件在任何 r/w 操作之前没有被另一个进程锁定

Posted

技术标签:

【中文标题】Java I/O:确保文件在任何 r/w 操作之前没有被另一个进程锁定【英文标题】:Java I/O: Ensure a file is not locked by another process before any r/w operation 【发布时间】:2012-02-06 19:36:30 【问题描述】:

我在基于 Java 7 WatchService API 跟踪目录中文件内容的应用程序中遇到了一个反复出现的问题。当底层文件系统对文件触发修改事件时,我想立即计算其 SHA-256。

但经常发生另一个进程打开了文件(即 Word),从而保留了排他锁并阻止我的应用程序进行任何读/写操作。如果针对打开的文件创建了任何 Stream/Channel,则会抛出 FileNotFoundException 或用于 nio API 的 FileSystemException,并带有如下消息:

该进程无法访问该文件,因为它正被另一个进程使用

当文件实际上不存在于 fs 上时,我无法提供一种解决方案来检测此类情况,而不掩盖“真实”的 FileNotFoundException。

我想出了通过 File.exists 检查存在性的想法,然后如果在我打开流时抛出 FileNotFoundException,我将能够推断出文件已被锁定。我愿意接受任何意见!

谢谢!

【问题讨论】:

找到解决方案了吗? 我最终使用了提到的启发式方法,如果 File.exists 在 FileNotFoundException catch 块中返回 true,我将其解释为文件锁定。 【参考方案1】:

您是否尝试过自己锁定文件?我假设您只能在未锁定且存在的情况下获取锁。

http://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileChannel.html#tryLock%28%29

【讨论】:

我无法调用 tryLock(),因为当我尝试通过 RandomAccessFile 或 FileOutputStream 获取 FileChannel 时会引发上述异常。 在这种情况下,听起来您必须检查尝试访问这些文件时抛出的异常。如果文件被锁定,则无法调用 tryLock,我看不到它的意义。 我的猜测是本机应用程序可以拥有比 JVM 中可用的锁更多的限制性锁。【参考方案2】:

跨进程共享文档很棘手,尤其是在不使用专用文件系统(如 GFS 可以)时。我认为 Java 锁定 API 对您没有多大帮助,我认为您的想法是正确的尝试/失败策略...使用java 7,您可以使用WatchService 来监视文件更改,然后按照您的业务需求进行操作...您使用什么样的系统? Windows 在永恒期间保持对文件的句柄...

HTH 杰罗姆

【讨论】:

确实我已经有一个 WatchService 线程监听 FS 事件,暂时只在 Windows 上运行。无论如何,我知道没有办法访问那些锁定的文件,但我很惊讶 java.io 或 java.nio 中没有 API 来测试它们的可访问性。

以上是关于Java I/O:确保文件在任何 r/w 操作之前没有被另一个进程锁定的主要内容,如果未能解决你的问题,请参考以下文章

关于VS2017提示I/O文件操作函数需要加上_s的解决办法

Unix系统编程通用的I/O

javaSE I/O流—— File类

javaSE I/O流—— File类

深入理解JAVA I/O系列三:字符流详解

文件未关闭时对已关闭文件的 I/O 操作