代码之家  ›  专栏  ›  技术社区  ›  Tim

Java File方法“canWrite()”是否支持锁定?

  •  12
  • Tim  · 技术社区  · 16 年前

    我有一个Java应用程序,它监视一个文件夹中传入的XML文件。当检测到新文件时,我需要测试该文件是否当前未被更新且已关闭。我的想法是使用 File.canWrite() 为了测试这一点。这样做有什么问题吗?这是测试文件是否已完全写入的好方法吗?

    我抛出的其他想法是:

    • 解析传入的XML文件并进行测试 结束标签就在那里。
    • 检查EoF字符。

    我只是不确定这些方法中的任何一种都能处理所有情况。

    5 回复  |  直到 16 年前
        1
  •  14
  •   erickson    16 年前

    不,canWrite不适合此目的。一般来说,即使另一个进程正在写入,文件也是可写的。

    您需要更高级别的协议来协调锁定。如果您计划在单个平台上使用此代码,则可以使用 NIO's FileLock facility 。但请仔细阅读文档,并注意在许多平台上,锁只是建议。

    另一种方法是让一个进程使用进程无法识别的名称写入文件,然后在写入完成后将文件重命名为可识别的名称。在大多数平台上,如果源和目标是相同的文件系统卷,则重命名操作是原子性的。名称更改可能会使用不同的文件扩展名,甚至将文件从一个目录移动到另一个目录(在同一卷上)。

    因为在这种情况下,您只使用XML,所以寻找一个关闭标记是可行的,但这并不是万无一失的——如果在最终标记后有注释,或者作者没有写有效的XML怎么办?

    寻找EOF将 工作。即使作者刚刚打开文件,还没有写任何东西,EOF也会一直存在。如果不是这样,最简单的方法是允许读者在文件出现后立即开始解析;它只会一直阻塞,直到作者关闭文件。但文件系统不是这样工作的。每个文件都有结束,即使某个进程当前正在移动它。

        2
  •  4
  •   Cheekysoft Moz Morris    16 年前

    此外,如果你先进行检查,然后进行写入,那么你就有了种族状况。状态可能在检查和写入之间发生变化。有时,最好尝试做你想做的事情,并优雅地处理错误。可能是一种具有增加回退延迟时间的n次尝试重试机制。

    或者重新定义你的测试。在这种情况下,您或许可以在处理文件之前测试文件大小在一段时间内没有变化。

    另一种选择是将代码分成两部分,您可以有另一个线程(可能是石英任务)负责将完成的文件移动到主代码处理的不同目录中。

        3
  •  2
  •   Griff    15 年前

    在Windows中似乎有效的一件事是 -创建一个表示所讨论文件的File()对象(使用带有完整文件名的构造函数) -以相同的方式创建第二个相同的文件对象。 -尝试firstFile.renameTo(secondFile)

    对于未被其他应用程序打开进行编辑的文件(我使用Word进行了测试),此虚拟重命名练习似乎成功了,但如果它们是打开的,则失败。

    由于nw文件名=旧文件名,因此它不会创建任何其他工作。

        4
  •  1
  •   AdamC    16 年前

    据我所知,无法判断另一个进程当前是否有Java文件的打开句柄。一种选择是使用 FileLock 并非所有平台都支持这个类,但如果文件是本地的,并且写入文件的进程协同工作,那么这应该适用于任何支持锁的平台。

        5
  •  0
  •   suthsc    16 年前

    如果你同时控制读写器,那么一种潜在的锁定技术就是创建一个锁 目录 --这通常是一个原子操作,用于读取和写入过程持续时间。如果你采取这种方法,你必须管理一个进程的潜在故障,导致目录“挂起”。

    正如Cheekysoft所提到的,文件不是原子文件,不适合锁定。

    如果你不控制写入程序——例如,如果它是由FTP守护进程生成的——那么重命名技术或时间跨度延迟技术是你最好的选择。