检测File.Move是否需要'复制 - >删除'或仅更改文件系统表中的位置

时间:2011-09-08 06:17:31

标签: c# file-io filesystems

声明: 我会马上承认,我对文件系统如何运作的细节有相当多的无知。我一直在使用NTFS这么长时间以来我可以根据我目睹的行为推断出正在发生的事情,以及我从互联网上的dorking所学到的一切 - 但是...

我希望有一种方法可以检测当文件从“位置A”移动到“位置B”时,操作是否需要等同于'File.Copy - > File.Delete'或者它是否不会复制实际的文件数据,只是更新“主文件表”中的位置等。

出于各种目的,我有时会移动大量的大文件。我想在UI中报告进度。

我意识到当我调用File.Move并将文件从一个磁盘/分区上的某个位置移动到另一个磁盘/分区时,该函数将有效地“复制文件数据” - >删除'磁盘/分区之间'。当遇到这种情况时,我希望能够检测到这种情况会发生,所以我可以使用我编写的代码来复制文件并在传输字节时提供详细的进度报告,这样我就可以经常更新UI中的进度条。

当它在同一个磁盘/分区上时,由于更新主文件表中的位置非常快,我只需在我批处理的每个文件的file.Move功能完成时更新进度条。

使用.NET 4(C#),是否可以通过其他方式检测调用File.Move是否需要等效的'copy - >删除'操作或只是更新文件表而不是复制文件数据?

修改

正如我在下面的评论中所指出的,我认为可能的可能性的可能性将是检测给定的源文件位置和目标文件位置是否位于同一物理磁盘上。分区,如果是这样,这是否意味着我可以准确预测行为并决定调用哪些函数 - 内置的File.Move函数用于“近即时”更新文件系统表,我相信当移动到相同的磁盘/部件时,或者我更详细的'报告进度每'x'字节复制'自定义文件复制代码。文件传输速度在我的程序运行的机器上会有很大差异,所以我希望能够在可能的情况下报告详细的进度/当前的传输速度。

注 - 程序可能正在使用网络UNC路径,这些路径可以使用具有相同根路径的不同物理磁盘,即:\\ somename \ shares \ workfolder \ project可能位于不同的物理磁盘上,然后是\\ somename \ shares \ workfoldder \ otherproject。所以我需要一种方法来检测分区ID或物理磁盘ID,以查看同一磁盘/分区上是否有源和目标文件夹。

谢谢

6 个答案:

答案 0 :(得分:2)

您可以随时P / Invoke到MoveFileWithProgress。从粗略的阅读中,看起来它会在复制文件时为您提供更细微的进度,而不是移动。

或者,始终有SHFileOperation,它将为您提供Windows资源管理器UI和语义。

答案 1 :(得分:1)

我认为你不能以正常的方式发现这样的事情,因为你不应该关心。如果你可以测试这个,那么if和else的情况是什么,因为不能从中提取任何知识(除了转移的速度)。

在.net中,文件系统是抽象的,因此您只需将文件从一个地方移动到另一个地方,而无需知道您要从哪个分区/文件系统/网络驱动器进行复制。

对于您的具体问题,为什么不始终显示进度条并在两种情况下以特定间隔更新进度条。

答案 2 :(得分:1)

我很确定你不能这样做。

对于初学者来说,即使在NTFS上,仅查看本地驱动器的驱动器号也是不够的,因为you can mount a drive inside an empty folder on an existing drive。这意味着即使两个路径具有相同的驱动器号,它们仍然可以安装在不同的磁盘上。

进一步考虑外部共享,可能是安装在基于* nix的系统上并通过Samba公开的外部共享。 * nix符号链接使得无法通过单独查看路径来判断两条路径是否位于同一物理设备上 - 唯一的选择是查询远程计算机“这两条路径是否存在于同一驱动器上?”,我非常怀疑会暴露出来。

我只会使用File.Move并接受您没有获得进度更新。无论如何,编写自己的副本实现对我来说是一个“不是特别好的主意”。

答案 3 :(得分:0)

虽然不是100%正确(sym-links让它看起来像是一个大分区,而它们可能是不同的物理驱动器(从我的头顶像WHS使用扩展),我会说为进度条的目的假设停留在同一个分区(System.IO.Path.GetPathRoot),可能就足够了。

答案 4 :(得分:0)

我对监控传输速度和进度条一无所知,但是对于检测文件是否正在移动到不同的驱动器/分区的问题,您可以只比较目标和源文件的驱动器/分区字母。 ..

如果你使用File.Move的完整路径,你可以使用简单的东西:

if(sourcePath[0]!=destinationPath[0])
    //enable transfer speed monitoring

如果您使用相对路径,则需要使用更多的字符串路径解释来提取目标/源驱动器/分区。

如果我的解决方案太简单或者我没有看到其他问题,我很抱歉。

答案 5 :(得分:0)

您可以P / Invoke GetFileInformationByHandle()函数,该函数返回卷序列号。如果两个文件的卷序列号相同,则它们位于同一卷上,不需要复制和删除。