1

事实:

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

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

问题:

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

我正在传输大文件(700 多兆),并且会针对每种情况采取不同的行为。


编辑:

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

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

4

2 回答 2

4

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

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

我看到您正在使用 Java——必须有一些门户,您可以通过该门户访问此操作系统级别的信息(也许是 JNI?)

于 2009-04-10T06:47:01.353 回答
2

好的,我在做某事:)

使用JNA,我可以从 java调用 Win32 API(和 *nix API)。

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

然后我在 MSDN 上看到了这个功能:MoveFileEx. 当标志参数设置为 0 时,移动复制功能将被禁用。它有效!!!!

所以我会简单地打电话

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;
于 2009-04-10T08:34:23.063 回答