为什么 FileInfo Length 与传递给 CopyFileEx 进度的 TotalFileSize 不匹配
Why does FileInfo Length not match the TotalFileSize passed to progress of CopyFileEx
我正在编写一个备份实用程序。这是我的第一个 C# 表单应用程序。
对于大多数文件,FileInfo length() 与传递给 CopyFileEx 进度处理程序的 TotalFileSize 匹配。但是,对于一个文件,我发现 FileInfo length() 小于传递给进度处理程序的 TotalFileSize。
程序使用 FileInfo 来计算要复制的所有文件的总大小
它使用带有进度处理程序的 CopyFileEx 来复制文件。
progress handler 用于更新所有数据复制比例的进度条。
我的问题是有时复制的总字节数大于预期的总字节数。
我的调查表明,对于大多数文件,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:
的文档之间有提示
The total number of bytes in the current stream that have been transferred from the source file to the destination file since the copy operation began.
以及您看到的输出:
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
流,因为这是从互联网下载并复制该流的 26 字节时创建的公共流。
您可以使用 Sysinternals 中的 Streams tool 查看文件的不同流,或使用 FindFirstStream
/ FindNextStream
从代码中枚举它们。
我正在编写一个备份实用程序。这是我的第一个 C# 表单应用程序。
对于大多数文件,FileInfo length() 与传递给 CopyFileEx 进度处理程序的 TotalFileSize 匹配。但是,对于一个文件,我发现 FileInfo length() 小于传递给进度处理程序的 TotalFileSize。
程序使用 FileInfo 来计算要复制的所有文件的总大小 它使用带有进度处理程序的 CopyFileEx 来复制文件。 progress handler 用于更新所有数据复制比例的进度条。
我的问题是有时复制的总字节数大于预期的总字节数。
我的调查表明,对于大多数文件,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:
的文档之间有提示The total number of bytes in the current stream that have been transferred from the source file to the destination file since the copy operation began.
以及您看到的输出:
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
流,因为这是从互联网下载并复制该流的 26 字节时创建的公共流。
您可以使用 Sysinternals 中的 Streams tool 查看文件的不同流,或使用 FindFirstStream
/ FindNextStream
从代码中枚举它们。