我有一组文件。这组文件是NTFS共享的只读文件,因此可以有许多读者。每个文件偶尔由一个具有写访问权限的编写器更新。
我如何确保:
我正在使用Java,我当前的解决方案是让编写者写入临时文件,然后使用File.renameTo()
将其与现有文件交换出来。问题出在NTFS上,如果目标文件已经存在,renameTo
会失败,所以你必须自己删除它。但是如果编写器删除目标文件然后失败(计算机崩溃),我没有可读文件。
nio的FileLock只能使用相同的JVM,所以对我来说没用。
如何使用Java安全地更新许多读者的文件?
答案 0 :(得分:3)
根据JavaDoc:
此文件锁定API旨在 直接映射到本机锁定 基础经营的设施 系统。因此锁定在文件上 应该对所有程序都可见 无论如何都可以访问该文件 这些程序的语言 写的。
答案 1 :(得分:1)
我不知道这是否适用,但如果您运行的是纯Vista / Windows Server 2008解决方案,我会使用TxF(事务性NTFS),然后确保打开文件句柄并执行文件操作通过JNI调用适当的文件API。
如果这不是一个选项,那么我认为你需要有一些所有客户都可以访问的服务,负责协调文件的读/写。
答案 2 :(得分:1)
在Unix系统上,我将删除该文件,然后将其打开以进行写入。任何让它开放阅读的人仍会看到旧的,一旦他们全部关闭它,它将从文件系统中消失。我不知道NTFS是否有类似的语义,虽然我听说它基于BSD的文件系统而丢失,所以也许它确实如此。
答案 3 :(得分:1)
无论什么操作系统等,都应该始终有效的东西正在改变您的客户端软件。
如果这是一个选项,那么你可以有一个文件“settings1.ini”,如果你想改变它,你创建一个文件“settings2.ini.wait”,然后把你的东西写到它,然后重命名它到“settings2.ini”然后删除“settings1.ini”。
您更改的客户端软件只会检查settings2.ini是否已读取settings1.ini,反之亦然。
这样你就可以随时使用。
答案 4 :(得分:0)
可能不需要锁定。我不太熟悉Windows上的FS API,但由于NTFS支持硬链接和软链接AFAIK,如果你的设置允许,你可以试试这个:
使用硬链接或软链接指向实际文件,并且不同地命名文件。让每个人都使用链接名称访问该文件。
在同一文件夹中以不同的名称编写新文件。
完成后,让文件指向新文件。最理想的是,Windows允许您通过在一个原子操作中替换现有链接来创建新链接。然后,您将有效地使链接始终标识有效文件,无论是旧文件还是新文件。在最坏的情况下,您必须先删除旧的,然后创建指向新文件的链接。在这种情况下,程序将无法找到文件的时间跨度很短。 (此外,Mac OS X提供了一个“ExchangeObjects”功能,允许您以原子方式交换两个项目 - 也许Windows提供类似的东西。)
这样,任何已经打开旧文件的程序都将继续访问旧文件,您将无法创建新文件。只有当应用程序注意到新版本的存在时,它才会关闭当前并再次打开它,这样就可以访问新版本了。
但是,我不知道如何在Java中创建链接。也许你必须使用一些原生API。
我希望无论如何这都有帮助。
答案 5 :(得分:-1)
我最近一直在处理类似的事情。如果您正在运行Java 5,也许您可以考虑将NIO文件锁与ReentrantReadWriteLock结合使用?确保引用FileChannel对象的所有代码都引用了ReentrantReadWriteLock。这样,NIO将其锁定在每个VM级别,而可重入锁定将其锁定在每个线程级别。
FileLock fileLock = filechannel.lock(position, size, shared);
reentrantReadWriteLock.lock();
// do stuff
fileLock.release();
reentrantReadWriteLock.unlock();
当然,需要进行一些异常处理。