如何确定文件是逻辑移动还是物理移动

时间:2009-04-10 06:14:32

标签: java file-io filesystems nio

事实:

移动文件时,有两种可能性:

  1. 源文件和目标文件位于同一分区,只更新文件系统索引
  2. 源和目标位于两个不同的文件系统上,文件需要每字节移动一个字节。 (又名移动时复制)
  3. 问题:

    如何判断文件是逻辑移动还是物理移动?

    我正在传输大文件(700+ megs),并会针对每种情况采用不同的行为。


    编辑:

    我已经编写了一个带有工作线程的移动文件对话框,该工作线程执行阻止调用以一次复制文件。它向用户提供信息,如粗略估计剩余时间和传输速率。

    问题是:在尝试物理移动文件之前,如何知道文件是否可以逻辑移动?

2 个答案:

答案 0 :(得分:4)

在Linux或其他目标上,在源和目标目录上调用stat()并比较它们的st_dev值。如果它们相同,则可以执行逻辑移动,否则必须执行物理复制+删除。

在Windows上,您可以在两个目录的句柄上调用GetFileInformationByHandle()并比较它们的dwVolumeSerialNumber值。请注意,这需要Windows 2000或更高版本。

我看到你正在使用Java - 必须有一些门户网站可以通过它访问这个操作系统级别的信息(也许是JNI?)

答案 1 :(得分:2)

好的我正在做点什么:)

使用 JNA 我能够从java调用Win32 API (以及* nix API)

我尝试调用GetFileInformationByHandle并确实得到了结果但dwVolumeSerialNumber属性始终等于0(尝试使用我的C:和D:驱动器)

然后我在MSDN上看到了这个功能:MoveFileEx。当flag参数设置为0时,将禁用复制移动功能。 AND IT WORKS !!!!

所以我只需要打电话

if (!Kernel32.INSTANCE.MoveFileEx(source.getAbsolutePath(), destination.getAbsolutePath(), 0)) {
    System.out.println("logical move failed");
}

以下是放入Kernel32.java界面的代码(此文件可在 JNA 网站的下载部分的src.zip包中找到):

boolean MoveFileEx(String lpExistingFileName, String lpNewFileName, int dwFlags);

int MOVEFILE_REPLACE_EXISTING = 0x01;
int MOVEFILE_COPY_ALLOWED = 0x02;
int MOVEFILE_CREATE_HARDLINK = 0x04;
int MOVEFILE_WRITE_THROUGH = 0x08;
int MOVEFILE_DELAY_UNTIL_REBOOT = 0x10;
int MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20;