7

我正在尝试使用FileLock在 Windows 环境中使用 Java 锁定文件,但遇到了一个问题:锁定文件后,其他进程至少在某种程度上仍然可以访问它。

示例代码如下:

public class SimpleLockExample {
    public static void main(String[] args) throws Exception {
        String filename = "loremlipsum.txt";

        File file = new File(filename);
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        FileChannel channel = raf.getChannel();

        FileLock lock = null;
        try {
            lock = channel.tryLock();
            String firstLine = raf.readLine();
            System.out.println("First line of file : " + firstLine);
            waitForEnter();
            lock.release();
        } catch (OverlappingFileLockException e) {
            e.printStackTrace();
        }

        lock.release();
        System.out.println("Lock released");

        channel.close();
    }

    private static void waitForEnter() throws Exception {
        BufferedReader reader =
                new BufferedReader(new InputStreamReader(System.in));
        reader.readLine();
        reader.close();
    }
}

现在,当我用这个例子锁定我的文件时,它被锁定:

  • Windows 无法删除
  • Eclipse 拒绝打开它

...但它仍然不是完全防弹的:

  • 例如,如果我使用 Scite(文本编辑器)打开它,则不会显示任何内容,但如果我选择保存文件(打开时为空或写入一些内容),它会成功并清除文件的内容.. . (即使我用 Scite 写了一些东西,之后也没有内容存在)

是否有某种方法可以完全防止文件被 Windows 中使用 Java 的其他进程覆盖/清除?

如果我理解正确,我正在使用独占锁 atm。使用共享锁可以做更多的事情。

此测试是在 Windows 2000 上运行的。

兄弟,图科

4

2 回答 2

5

棘手的是,FileLock API 本身并没有太多承诺:

此文件锁定 API 旨在直接映射到底层操作系统的本机锁定设施。因此,文件上的锁应该对所有有权访问该文件的程序可见,而不管这些程序是用什么语言编写的。

锁是否实际上阻止另一个程序访问锁定区域的内容是系统相关的,因此未指定。某些系统的本机文件锁定工具只是建议性的,这意味着程序必须协同遵守已知的锁定协议以保证数据完整性。在其他系统上,本地文件锁是强制性的,这意味着如果一个程序锁定了文件的某个区域,那么实际上会阻止其他程序以违反锁的方式访问该区域。在其他系统上,本机文件锁是建议性的还是强制性的,可以根据每个文件进行配置。为确保跨平台的一致和正确行为,

奇怪的是,关于文件锁定 API 在开发时的讨论声称 Windows 操作系统提供强制锁定,而在 Unix 上仅提供建议锁定。因此,在阅读时,您可能希望您的代码在 Windows 上运行良好。

我想知道您的编辑器不是在修改文件而是创建一个临时文件然后操作目录条目以用新版本替换您锁定的文件版本是怎么回事。Windows 会允许这种行为吗?

我想知道您是否需要借助 JNI 才能获得所需的控制级别。

于 2009-08-27T07:18:13.017 回答
1

如果没有获得锁,您对 .tryLock() 的调用可能会返回 null。来自 Javadoc:

表示新获得的锁的锁对象,如果由于另一个程序持有重叠锁而无法获得锁,则为 null

此外,您的代码当前打开文件,然后尝试获取锁。相反,您应该循环尝试获取锁,一旦获得锁,打开文件,读取文件,关闭文件,然后放弃锁。并在一个子句中放弃锁finally {},以防您的代码在持有锁的情况下抛出异常。(曾经因为某些文件被锁定而不得不重新启动 Windows 机器吗?)

于 2010-03-23T16:38:25.670 回答