簡體   English   中英

不使用 windows 文件緩存復制文件

[英]Copy a file without using the windows file cache

有人知道將文件從路徑 A 復制到路徑 B 並抑制 Windows 文件系統緩存的方法嗎?
典型用途是將大文件從 USB 驅動器或服務器復制到本地計算機。 如果文件真的很大,例如 2GiB,Windows 似乎會交換所有內容。 更喜歡 C# 中的示例,但我猜如果可能的話,這將是某種 Win32 調用。

在 C# 中,我發現類似這樣的東西可以工作,可以將其更改為直接復制到目標文件:

    public static byte[] ReadAllBytesUnbuffered(string filePath)
    {
        const FileOptions FileFlagNoBuffering = (FileOptions)0x20000000;
        var fileInfo = new FileInfo(filePath);
        long fileLength = fileInfo.Length;
        int bufferSize = (int)Math.Min(fileLength, int.MaxValue / 2);
        bufferSize += ((bufferSize + 1023) & ~1023) - bufferSize;
        using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None,
                                           bufferSize, FileFlagNoBuffering | FileOptions.SequentialScan))
        {
            long length = stream.Length;
            if (length > 0x7fffffffL)
            {
                throw new IOException("File too long over 2GB");
            }
            int offset = 0;
            int count = (int)length;
            var buffer = new byte[count];
            while (count > 0)
            {
                int bytesRead = stream.Read(buffer, offset, count);
                if (bytesRead == 0)
                {
                    throw new EndOfStreamException("Read beyond end of file EOF");
                }
                offset += bytesRead;
                count -= bytesRead;
            }
            return buffer;
        }
    }

更重要的是,還有 FILE_FLAG_WRITE_THROUGH 和 FILE_FLAG_NO_BUFFERING。

MSDN 上有一篇關於它們的好文章: http : //support.microsoft.com/kb/99794

我不確定這是否有幫助,但請查看 使用 FILE_FLAG_SEQUENTIAL_SCAN 提高性能

總結

CreateFile() 有一個名為 FILE_FLAG_SEQUENTIAL_SCAN 的標志,它將指示緩存管理器按順序訪問文件。

任何通過順序訪問讀取潛在大文件的人都可以指定此標志以提高性能。 如果您正在讀取“大部分”順序的文件,但偶爾會跳過小范圍的字節,則此標志很有用。

如果您不介意使用工具,ESEUTIL 對我來說效果很好。

您可以查看此博客條目,比較緩沖和非緩沖 IO 函數以及從何處獲取 ESEUTIL。

從technet博客復制一些文本:

因此,查看上面緩沖 I/O 的定義,我們可以看到感知到的性能問題所在——文件系統緩存開銷。 當我們不打算在復制完成后訪問源文件時,嘗試將大文件從一個位置復制到另一個位置時,首選無緩沖 I/O(或原始文件副本)。 這將避免文件系統緩存開銷並防止文件系統緩存被大文件數據有效刷新。 許多應用程序通過調用 CreateFile() 創建一個空的目標文件,然后使用 ReadFile() 和 WriteFile() 函數來傳輸數據來實現這一點。 CreateFile() - CreateFile 函數創建或打開文件、文件流、目錄、物理磁盤、卷、控制台緩沖區、磁帶驅動器、通信資源、郵槽或命名管道。 該函數返回可用於訪問對象的句柄。 ReadFile() - ReadFile 函數從文件中讀取數據,並從文件指針指示的位置開始。 您可以將此函數用於同步和異步操作。 WriteFile() - WriteFile 函數在文件指針指定的位置將數據寫入文件。 此函數設計用於同步和異步操作。 為了在網絡上復制非常大的文件,我選擇的復制實用程序是 ESEUTIL,它是 Exchange 提供的數據庫實用程序之一。

Eseutil 是一個正確的答案,也是從 Win7 / 2008 R2 開始,您可以在 Xcopy 中使用 /j 開關,它具有相同的效果。

我知道這個問題是 11 年前的問題,現在有 robocopy 可以替代 xcopy。

您需要檢查 /J 選項/J :: copy using unbuffered I/O (recommended for large files)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM