我有一组文件。该组文件在 NTFS 共享之外是只读的,因此可以有多个读者。每个文件都会由具有写访问权限的写入者偶尔更新。

我如何确保:

  1. 如果写入失败,则之前的文件仍然可读
  2. 读者扛不住单个作者

我正在使用 Java,我当前的解决方案是让编写者写入临时文件,然后使用以下命令将其与现有文件交换 File.renameTo(). 。问题出在 NTFS 上, renameTo 如果目标文件已经存在则失败,因此您必须自己删除它。但是如果编写者删除了目标文件然后失败(计算机崩溃),我就没有可读的文件。

nio 的 FileLock 只能在同一个 JVM 上工作,所以对我来说没用。

如何使用 Java 安全地更新有许多读者的文件?

有帮助吗?

解决方案

根据 JavaDoc

  

此文件锁定API旨在   直接映射到本机锁定   基础经营的设施   系统。因此锁定在文件上   应该对所有程序都可见   无论如何都可以访问该文件   这些程序的语言   写的。

其他提示

我不知道这是否适用,但如果您运行的是纯Vista / Windows Server 2008解决方案,我会使用TxF(事务性NTFS),然后确保打开文件句柄并执行文件操作通过JNI调用适当的文件API。

如果这不是一个选项,那么我认为你需要有一些所有客户都可以访问的服务,负责协调文件的读/写。

在Unix系统上,我将删除该文件,然后将其打开以进行写入。任何让它开放阅读的人仍会看到旧的,一旦他们全部关闭它,它将从文件系统中消失。我不知道NTFS是否有类似的语义,虽然我听说它基于BSD的文件系统而丢失,所以也许它确实如此。

无论什么操作系统等,都应该始终有效的东西正在改变您的客户端软件。

如果这是一个选项,那么你可以有一个文件“settings1.ini”。如果你想改变它,你创建一个文件“settings2.ini.wait”,然后把你的东西写到它,然后将它重命名为“settings2.ini”。然后删除“settings1.ini”。

您更改的客户端软件只会检查settings2.ini是否已读取settings1.ini,反之亦然。

这样你就可以随时使用。

可能不需要锁定。我不太熟悉Windows上的FS API,但由于NTFS支持硬链接和软链接AFAIK,如果你的设置允许,你可以试试这个:

使用硬链接或软链接指向实际文件,并且不同地命名文件。让每个人都使用链接名称访问该文件。

在同一文件夹中以不同的名称编写新文件。

完成后,让文件指向新文件。最理想的是,Windows允许您通过在一个原子操作中替换现有链接来创建新链接。然后,您将有效地使链接始终标识有效文件,无论是旧文件还是新文件。在最坏的情况下,您必须先删除旧的,然后创建指向新文件的链接。在这种情况下,程序将无法找到文件的时间跨度很短。 (此外,Mac OS X提供了一个“ExchangeObjects”功能,允许您以原子方式交换两个项目 - 也许Windows提供类似的东西。)

这样,任何已经打开旧文件的程序都将继续访问旧文件,您将无法创建新文件。只有当应用程序注意到新版本的存在时,它才会关闭当前并再次打开它,这样就可以访问新版本了。

但是,我不知道如何在Java中创建链接。也许你必须使用一些原生API。

我希望无论如何这都有帮助。

我最近一直在处理类似的事情。如果您运行的是 Java 5,也许您可​​以考虑将 NIO 文件锁与 ReentrantReadWriteLock 结合使用?确保引用 FileChannel 对象的所有代码也引用 ReentrantReadWriteLock。这样,NIO 将其锁定在每个虚拟机级别,而可重入锁将其锁定在每个线程级别。

FileLock fileLock = filechannel.lock(position, size, shared);
reentrantReadWriteLock.lock();

// do stuff

fileLock.release();
reentrantReadWriteLock.unlock();

当然,需要一些异常处理。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top