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

使用Commons IO复制时锁定文件

  •  4
  • Joshua  · 技术社区  · 17 年前

    我正在使用Apache Commons IO:

         FileUtils.copyFileToDirectory(srcFile, destDir)
    

    如何使Windows在复制过程中锁定目标文件?如果我使用以下命令,Windows将正确锁定文件:

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

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

    3 回复  |  直到 17 年前
        1
  •  6
  •   Community Mohan Dere    6 年前

    java.nio.channels.FileChannel 将允许您获得 FileLock 在文件上,使用底层文件系统固有的方法,假设支持此类功能。

    这个锁在机器上的进程之间运行,即使是非java进程。(事实上,锁是代表特定JVM实例持有的,因此不适合管理进程中多个线程之间的争用,也不适合管理同一JVM中多个进程之间的争用)。

    这里有很多注意事项,但是如果您使用的是Windows,则值得研究。

    从javadoc:

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

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

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

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

        2
  •  4
  •   Kevin    17 年前

    Java本机不支持文件锁定。

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

    这将有助于获得更多关于为什么首先需要锁定文件的信息。

    争用不在本地 程序,但是一个外部程序。档案 正在将复制到远程系统。 远程系统正在处理 在完成复制之前创建文件。 因为系统是Windows,所以 普通复制会锁定文件和块 来自access的外部程序。

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

        3
  •  1
  •   Aaron Digulla    17 年前

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

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

    推荐文章