事实:
移动文件时,有两种可能性:
- 源文件和目标文件在同一个分区,只更新文件系统索引
- 源和目标位于两个不同的文件系统上,文件需要逐字节移动。(又名移动复制)
问题:
如何确定文件是逻辑移动还是物理移动?
我正在传输大文件(700 多兆),并且会针对每种情况采取不同的行为。
编辑:
我已经编写了一个带有工作线程的移动文件对话框,该线程执行阻塞 io 调用以一次复制文件一个兆。它向用户提供信息,例如粗略估计剩余时间和传输速率。
问题是:在尝试物理移动文件之前,我如何知道文件是否可以在逻辑上移动?
事实:
移动文件时,有两种可能性:
问题:
如何确定文件是逻辑移动还是物理移动?
我正在传输大文件(700 多兆),并且会针对每种情况采取不同的行为。
编辑:
我已经编写了一个带有工作线程的移动文件对话框,该线程执行阻塞 io 调用以一次复制文件一个兆。它向用户提供信息,例如粗略估计剩余时间和传输速率。
问题是:在尝试物理移动文件之前,我如何知道文件是否可以在逻辑上移动?
在 Linux 或其他 *nicesstat()上,调用源目录和目标目录并比较它们的st_dev值。如果相同,则可以进行逻辑移动,否则必须进行物理复制+删除。
在 Windows 上,您可以调用GetFileInformationByHandle()两个目录的句柄并比较它们的dwVolumeSerialNumber值。请注意,这需要 Windows 2000 或更高版本。
我看到您正在使用 Java——必须有一些门户,您可以通过该门户访问此操作系统级别的信息(也许是 JNI?)
好的,我在做某事:)
使用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;