【问题标题】:Locking a file while copying using Commons IO使用 Commons IO 复制时锁定文件
【发布时间】:2010-10-03 04:04:01
【问题描述】:

我正在使用 Apache Commons IO:

     FileUtils.copyFileToDirectory(srcFile, destDir)

如何让 Windows 在复制过程中锁定目标文件?如果我使用,Windows 会正确锁定文件:

      Runtime.getRuntime().exec(
      "cmd /c copy /Y \"" + srcFile.getCanonicalPath() + "\" \""
          + destDir.getCanonicalPath() + "\"").waitFor();

注意事项: 争论不在于本地程序,而在于外部程序。正在将文件复制到远程系统。远程系统在完成复制之前正在处理文件。因为系统是Windows,所以普通副本会锁定文件并阻止外部程序访问。

【问题讨论】:

    标签: java windows file-io apache-commons


    【解决方案1】:

    java.nio.channels.FileChannel 将允许您使用底层文件系统的本机方法获取文件上的FileLock,前提是支持此类功能。

    此锁跨机器上的进程运行,甚至是非 java 进程。 (实际上,锁是代表特定的JVM实例持有的,所以不适合管理一个进程中的多个线程之间的争用,或者同一个JVM中的多个进程)。

    这里有很多警告,但如果您在 Windows 上工作,则值得调查。

    来自 javadoc:

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

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

    在某些系统上,获取文件区域的强制锁定会阻止该区域映射到内存中,反之亦然。结合锁定和映射的程序应该为这种结合失败做好准备。

    在某些系统上,关闭通道会释放 Java 虚拟机在基础文件上持有的所有锁,无论这些锁是通过该通道还是通过同一文件上打开的另一个通道获得的。强烈建议在程序中使用唯一通道来获取任何给定文件上的所有锁。

    某些网络文件系统仅在锁定区域是页面对齐且是底层硬件页面大小的整数倍时才允许对内存映射文件使用文件锁定。一些网络文件系统不会在超出某个位置(通常是 230 或 231)的区域上实现文件锁定。通常,在锁定驻留在网络文件系统上的文件时应格外小心。`

    【讨论】:

      【解决方案2】:

      Java 本身不支持文件锁定。

      如果文件的争用来自您的程序,也许您需要在文件副本之上构建额外的同步,以确保并发写入不会相互干扰。但是,如果争用来自软件外部的某个地方,那么您无能为力。您可以尝试将文件写入临时目录,然后重命名它,因为重命名或多或少是原子的(取决于文件系统)。

      首先了解为什么需要锁定文件会有所帮助。

      不与本地争用 程序,而是一个外部程序。文件 正在复制到远程系统。 远程系统正在处理 完成复制之前的文件。 因为系统是 Windows, 普通副本锁定文件和块 访问外部程序。

      在这种情况下,您应该尝试写入临时文件,然后在文件完全复制后重命名。文件重命名是原子操作(在非网络文件系统上),所以它应该适合你。

      【讨论】:

        【解决方案3】:

        复制文件时,请始终复制到临时文件名,并在完成写入后重命名文件。这样,另一个进程永远不会看到损坏的文件。

        更好的是,您可以写入 *.tmp。然后检查目标文件是否存在。将 dest 文件重命名为 *.bak(如果存在)。最后重命名 *.tmp -> dest.

        【讨论】:

          猜你喜欢
          • 2012-04-07
          • 2019-04-30
          • 2011-08-24
          • 1970-01-01
          • 2016-06-29
          • 2014-06-12
          • 1970-01-01
          • 2023-03-26
          • 1970-01-01
          相关资源
          最近更新 更多