Java 文件锁定和 Windows - 锁定不是“绝对的”?

发布于 2024-08-03 06:19:07 字数 1602 浏览 9 评论 0 原文

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

示例代码如下:

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 上运行的

。br, 灯子

I'm trying to lock a file with Java in Windows environment with FileLock and I got an issue :
after I lock the file it can still be accessed by other processes at least on some level.

Example code follows:

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();
    }
}

Now, when I lock my file with this example, it is locked :

  • It can't be deleted by Windows
  • Eclipse refuses to open it

... but it isn't still totally bulletproof:

  • If I open it with Scite (a text editor), for example, no content is shown but if I select to save the file (empty as opened or with some content written), it succeeds and the contents of the file is cleared... (no content exists there afterwards even if I had written something with Scite)

Is there some way to prevent the file totally from being overwritten/cleared by other processes with Java in Windows?

If I've understood right, I'm using exclusive lock atm. With shared lock there are even more things that can be done.

This test was run with Windows 2000.

br,
Touko

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

葬シ愛 2024-08-10 06:19:07

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

此文件锁定 API 旨在
直接映射到本机锁定
底层运营设施
系统。因此,文件上持有的锁
应该对所有程序可见
有权访问该文件,无论
这些程序所使用的语言
已写。

实际上是否有锁
阻止另一个程序
访问锁定的内容
区域是系统相关的并且
因此未指定。当地人
一些文件锁定设施
系统只是建议性的,意味着
该计划必须合作
遵守已知的锁定协议
以保证数据的完整性。在
其他系统本机文件锁是
强制性的,这意味着如果一个程序
锁定文件的一个区域,然后锁定其他区域
程序实际上被阻止
以某种方式访问​​该区域
会违反锁。还有其他的
系统,是否有本机文件锁
建议性或强制性可配置
基于每个文件。为确保
一致且正确的行为
平台,强烈推荐
该 API 提供的锁是
就好像它们是咨询锁一样使用。

奇怪的是,有关文件锁定 API 开发时的讨论声称 Windows 操作系统提供强制锁定,而在 Unix 上仅提供建议性锁定。因此,读完这篇文章后,人们可能会期望您的代码在 Windows 上运行得很好。

我想知道是否发生了什么事,您的编辑器不是修改文件而是创建临时文件,然后操作目录条目以便用新版本替换您已锁定的文件版本。 Windows 会允许这种行为吗?

我想知道您是否需要求助于 JNI 以获得所需的控制级别。

Tricky, the FileLock API itself doesn't promise much:

This file-locking API is intended to
map directly to the native locking
facility of the underlying operating
system. Thus the locks held on a file
should be visible to all programs that
have access to the file, regardless of
the language in which those programs
are written.

Whether or not a lock actually
prevents another program from
accessing the content of the locked
region is system-dependent and
therefore unspecified. The native
file-locking facilities of some
systems are merely advisory, meaning
that programs must cooperatively
observe a known locking protocol in
order to guarantee data integrity. On
other systems native file locks are
mandatory, meaning that if one program
locks a region of a file then other
programs are actually prevented from
accessing that region in a way that
would violate the lock. On yet other
systems, whether native file locks are
advisory or mandatory is configurable
on a per-file basis. To ensure
consistent and correct behavior across
platforms, it is strongly recommended
that the locks provided by this API be
used as if they were advisory locks.

Oddly enough, the discussion about the file locking API when it was under development claimed that Windows OS provided mandatory locking and on Unix only advisory locking. So on that reading one might expect your code to work just fine on Windows.

I wonder if what is happening it that your editor is not so much modifying the file as creating a temporary file and then manipulating directory entries in order to replce the version of the file you have locked with a new version. Would Windows allow such behaviour?

I wonder if you'll need to resort to JNI in order to get the level of control you need.

十级心震 2024-08-10 06:19:07

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

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

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

Your call to .tryLock() may return null if it doesn't get the lock. From the Javadoc:

A lock object representing the newly-acquired lock, or null if the lock could not be acquired because another program holds an overlapping lock

Also, your code currently opens the file and then it tries to acquire a lock. Instead you should loop trying to get the lock, and once you've got it, open the file, read the file, close the file, then give up the lock. And give up the lock in a finally {} clause, just in case your code throws an exception with the lock held. (Ever had to reboot a Windows machine just because some file was locked?)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文