繁体   English   中英

为什么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与进度处理程序一起使用来复制文件。 进度处理程序用于为所有要复制的数据的比例更新进度条。

我的问题是有时复制的字节总数大于预期的总数。

我的调查表明,对于大多数文件,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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM