开发者

Detecting if File.Move will require 'Copy -> Delete' or just alter location in the file system table

Disclaimer: I will admit straight away I have a fair amount of ignorance regarding the details on how file systems function. I have been using NTFS for so long that I can extrapolate what is going on based on behaviors I have witnessed, as well as whatever I have learned from dorking on the internet - however...

I was hoping that there is a way to detect if when moving a file from 'location A' to 'location B', whether the operation will require the equivalent of 'File.Copy -> File.Delete' or if it will not copy the actual file data, but just update the location in the 'master file table' or the like.

For various purposes, I sometimes move large numbers of large files. I like to report progress in the UI.

I realize that when I call File.Move and move a file from a location on one disk/partition to another, that the function will effectively have to 'copy file data -> delete' between the disks / partitions. When it encounters this situation, I want to be able to detect that this will happen so I can use code I have authored that will copy the file and give detailed progress reporting as bytes are transferred so I can update progress bars in the UI frequently.

When it is on the same disk/partition, as updating the location in the master file table is so fast, I simply update the progress bar when the file.Move function completes for each file I am batch moving.

Using .NET 4 (C#), is it possible to detect through other means whether calling the File.Move will require an equivalent 'copy -> delete' operation or will simply update a file table and not copy the file data?

Edit:

As I note in comments below, possibilities on how I thought this might be done would be to detect if a given source file location and destination file location are located on the same physical disk & partition, and if so, would this mean I could accurately anticipate the behavior and decide what functions to call - the built in File.Move function for the 'near instant' update file system table that I believe occurs when moving to same disk/part, or my more detailed 'report progress every 'x' bytes copied' custom file copy 开发者_运维百科code. File transfer speeds can vary greatly on the machines my programs will run on so I like to be able to report detailed progress / present transfer speed when possible.

Note - The program may be using network UNC paths which can be using different physical disks with the same root path i.e.: \\somename\shares\workfolder\project may be on a different physical disk then \\somename\shares\workfoldder\otherproject. So I would need a method for detecting the partition ID or physical disk ID to see if a source and destination folder on on the same disk/partition.

Thank you


You could always P/Invoke to MoveFileWithProgress. From a cursory reading, it looks like it'll give you more granular progress when a file is copied, rather than moved.

Alternatively, there's always SHFileOperation, which'll give you the Windows Explorer UI and semantics.


I don't think you can detect such a thing in a normal way as you're not supposed to care. If you could test this, what would be the if and else case be as no knowledge can be extracted from this (except for the speed of the transfer).

In .net the file system is abstracted so you can just move files from one place to another without knowing what partition/filesystem/network drive you're copying from/to.

For your specific problem, why don't you always show the progressbar and have it updated at a certain interval for both cases.


I'm pretty sure that you can't do this.

For starters even on NTFS just looking at the drive letter for local drives isn't enough because you can mount a drive inside an empty folder on an existing drive. This means that even if the two paths have the same drive letter they could still be mounted on different disks.

To take it another step further consider external shares, possibly ones mounted on an *nix based system and exposed via Samba. *nix symbolic links make it impossible to tell whether two paths reside on the same physical device by looking at paths alone - the only option have would be to query the remote machine "do these two paths exist on the same drive?", something which I very much doubt would be exposed.

I would just use File.Move and accept that you don't get progress updates. Writing your own copy implementation strikes me as a "not a particularly good idea" anyway.


While not 100% correct (sym-links make it look like things are one big partition while they may be different physical drives (from the top of my head like WHS uses extensivly), I would say for the purpose of progress bar assuming that staying on the same partition (System.IO.Path.GetPathRoot), will probably be enough.


I don't know anything about monitoring transfer speed and progress bars but for the issue of detecting if a file is being move to a diffrent drive/partition you could just compare the drive/partition letter of the destination and source file...

if you are using full paths for File.Move you could use something as simple as:

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

if you are using relative paths you need to extract the destination/source drive/partition with a little more string path interpreting.

I'm sorry if my solution is too simple or if I'm not seeing some other problem.


You can P/Invoke the GetFileInformationByHandle() function, which returns the volume serial number. If the volume serial number is the same for both files, they are on the same volume and no copy-and-delete will be necessary.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜