复制文件而不使用Windows文件缓存

问题描述 投票:6回答:6

有人知道一种将文件从路径A复制到路径B并抑制Windows文件系统缓存的方法吗?通常的用途是将大文件从USB驱动器或服务器复制到本地计算机。如果文件很大,Windows似乎会交换所有内容,例如2GiB。更喜欢用C#编写示例,但我想如果可能的话,这将是某种Win32调用。

c# windows winapi filesystems file-copying
6个回答
5
投票

更重要的是,有FILE_FLAG_WRITE_THROUGH和FILE_FLAG_NO_BUFFERING。

MSDN上有一篇不错的文章:http://support.microsoft.com/kb/99794


6
投票

在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;
        }
    }

4
投票

我不确定这是否有帮助,但请查看Increased Performance Using FILE_FLAG_SEQUENTIAL_SCAN

摘要

[CreateFile()有一个标志名为FILE_FLAG_SEQUENTIAL_SCAN会将缓存管理器定向到顺序访问文件。

任何人都可能读取大文件具有顺序访问权限的用户可以指定此标志可提高性能。如果您正在阅读此标志很有用“大部分”是连续的文件,但是你偶尔会跳过小字节范围。


3
投票

[如果您不介意使用工具,ESEUTIL对我来说很棒。

您可以比较缓冲的和非缓冲的IO功能以及从何处获取ESEUTIL的blog条目。

从technet博客复制一些文本:

因此,通过查看上面的缓冲I / O的定义,我们可以看到感知的性能问题在哪里-文件系统缓存的开销。当我们不打算在复制完成后访问源文件时,尝试将大文件从一个位置复制到另一个位置时,最好使用无缓冲的I / O(或原始文件副本)。这将避免文件系统缓存的开销,并防止大型文件数据有效刷新文件系统缓存。许多应用程序通过调用CreateFile()创建一个空的目标文件,然后使用ReadFile()和WriteFile()函数来传输数据来实现此目的。CreateFile()-CreateFile函数创建或打开文件,文件流,目录,物理磁盘,卷,控制台缓冲区,磁带驱动器,通信资源,邮筒或命名管道。该函数返回可用于访问对象的句柄。ReadFile()-ReadFile函数从文件读取数据,并从文件指针指示的位置开始。您可以将此功能用于同步和异步操作。WriteFile()-WriteFile函数在文件指针指定的位置将数据写入文件。此功能设计用于同步和异步操作。对于在网络上复制非常大的文件,我选择的复制实用程序是ESEUTIL,它是Exchange附带的数据库实用程序之一。


1
投票

Eseutil是正确的答案,而且从Win7 / 2008 R2开始,您可以使用Xcopy中的/ j开关,其效果相同。


0
投票

我知道这个问题是11年前的,如今有robocopy可以替代xcopy。

您需要检查/ J选项/J :: copy using unbuffered I/O (recommended for large files)

© www.soinside.com 2019 - 2024. All rights reserved.