簡體   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