[英]Why does FileInfo Length not match the TotalFileSize passed to progress of CopyFileEx
我正在编写一个备份实用程序。 这是我的第一个C#表单应用程序。
对于大多数文件,FileInfo length()与传递给CopyFileEx进度处理程序的TotalFileSize相匹配。 但是,对于仅一个文件,我发现FileInfo length()小于传递给进度处理程序的TotalFileSize。
该程序使用FileInfo来计算要复制的所有文件的总大小。它将CopyFileEx与进度处理程序一起使用来复制文件。 进度处理程序用于为所有要复制的数据的比例更新进度条。
我的问题是有时复制的字节总数大于预期的总数。
我的调查表明,对于大多数文件,FileInfo length()与传递给进度处理程序的TotalFileSize相匹配。 但是,对于一个文件,FileInfo length()小于传递给进度处理程序的TotalFileSize。
为什么大小不同?我该怎么做才能使计算出的文件总大小与复制的总字节数匹配?
private UnsafeNativeMethods.CopyProgressResult localHandler(Int64 TotalFileSize, Int64 TotalBytesTransferred, Int64 StreamSize,
Int64 StreamBytesTransferred, UInt32 StreamNumber, UnsafeNativeMethods.CopyProgressCallbackReason CallbackReason, IntPtr SourceFile,
IntPtr DestinationFile, IntPtr Data)
{
switch (CallbackReason)
{
case UnsafeNativeMethods.CopyProgressCallbackReason.CallbackChunkedFinished:
Debug.Print("localHandler: TotalBytesTransferred={0} TotalFileSize={1} ", TotalBytesTransferred.ToString(), TotalFileSize.ToString());
break;
case UnsafeNativeMethods.CopyProgressCallbackReason.CallbackStreamSwitch:
break;
default:
break;
}
return UnsafeNativeMethods.CopyProgressResult.ProgressContinue;
}
private void ButtonTestFileSize_Click(object sender, EventArgs e)
{
bool success;
bool b=false;
string inputFile= @"C:\temp\WrongFileSize\myFile.conf";
string outputFile= @"C:\temp\WrongFileSize\myFile.con2";
/* Get the input Filename using FileInfo */
FileInfo file = new FileInfo(inputFile);
Debug.Print("input FileInfo.length={0}", file.Length);
string hres = UnsafeNativeMethods.HResultToString(UnsafeNativeMethods.GetHResult((uint)Marshal.GetLastWin32Error()));
success = UnsafeNativeMethods.CopyFileEx(inputFile,
outputFile,
new UnsafeNativeMethods.CopyProgressRoutine(localHandler),
IntPtr.Zero,
ref b,
CopyFileFlags.FileFailIfExists | CopyFileFlags.COPY_FILE_NO_BUFFERING);
if (!success)
{
Debug.Print("Failed");
}
else
{
Debug.Print("Success");
}
/* Get the output Filename using FileInfo */
file = new FileInfo(outputFile);
Debug.Print("outputFile FileInfo.length={0}", file.Length);
}
}
此代码的输出如下:
input FileInfo.length=2636
localHandler: TotalBytesTransferred=2636 TotalFileSize=2662
localHandler: TotalBytesTransferred=2662 TotalFileSize=2662
Success
outputFile FileInfo.length=2636
这是因为您要复制的字节数比文件的主要流中的字节数多。 在CopyFileEx的LPPROGRESS_ROUTINE的文档之间有一个提示:
自复制操作开始以来,当前流中已从源文件传输到目标文件的字节总数。
和您看到的输出:
input FileInfo.length=2636
localHandler: TotalBytesTransferred=2636 TotalFileSize=2662
localHandler: TotalBytesTransferred=2662 TotalFileSize=2662
Success
outputFile FileInfo.length=2636
如果您向当前为空的UnsafeNativeMethods.CopyProgressCallbackReason.CallbackStreamSwitch
目标添加了一条消息,那么您显然会发现正在发生的事情。 基本上,您正在为主要流传输2636字节。 大多数查看文件大小的Win32 API仅在主要流上报告,而FileInfo()
在这里没有什么不同。
然后,您切换到文件上的一些辅助流,可能是:Zone.Identifier
流,因为这是从Internet下载并复制该流的26个字节时创建的普通流。
您可以使用Sysinternals中的Streams工具查看文件的不同流,或者使用FindFirstStream
/ FindNextStream
从代码中枚举它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.