有人知道将文件从路径A复制到路径B并抑制Windows文件系统缓存的方法吗? 典型用途是将大型文件从USB驱动器或服务器复制到本地计算机。如果文件非常大,Windows似乎会将所有内容都换掉,例如2GiB。 更喜欢C#中的示例,但我猜这可能是某种类型的Win32调用。
答案 0 :(得分: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;
}
}
答案 1 :(得分:5)
更重要的是,有FILE_FLAG_WRITE_THROUGH和FILE_FLAG_NO_BUFFERING。
MSDN上有一篇很好的文章:http://support.microsoft.com/kb/99794
答案 2 :(得分:4)
我不确定这是否有帮助,但请查看Increased Performance Using FILE_FLAG_SEQUENTIAL_SCAN。
概要
CreateFile()有一个标志 称为FILE_FLAG_SEQUENTIAL_SCAN 将指向缓存管理器 按顺序访问文件。
任何阅读潜在大文件的人 顺序访问可以指定 这个标志提高了性能。 如果您正在阅读,此标志非常有用 “大部分”顺序的文件, 但你偶尔跳过小 字节范围。
答案 3 :(得分:3)
如果您不介意使用工具,ESEUTIL对我来说非常有用。
您可以查看此blog条目,比较缓冲和非缓冲IO功能以及从何处获取ESEUTIL。
从technet博客中复制一些文字:
因此,看看上面缓冲I / O的定义,我们可以看到感知到的性能问题在于文件系统缓存开销。当我们在复制完成后不打算访问源文件时,尝试将大文件从一个位置复制到另一个位置时,首选无缓冲I / O(或原始文件复制)。这将避免文件系统缓存开销,并防止文件系统缓存被大文件数据有效刷新。许多应用程序通过调用CreateFile()来创建一个空的目标文件,然后使用ReadFile()和WriteFile()函数来传输数据来实现这一点。 CreateFile() - CreateFile函数创建或打开文件,文件流,目录,物理磁盘,卷,控制台缓冲区,磁带驱动器,通信资源,邮件槽或命名管道。该函数返回一个可用于访问对象的句柄。 ReadFile() - ReadFile函数从文件中读取数据,并从文件指针指示的位置开始。您可以将此功能用于同步和异步操作。 WriteFile() - WriteFile函数将数据写入文件指针指定位置的文件。此功能适用于同步和异步操作。 对于复制非常大的网络文件,我选择的复制实用程序是ESEUTIL,它是Exchange提供的数据库实用程序之一。
答案 4 :(得分:1)
Eseutil是一个正确的答案,从Win7 / 2008 R2开始,你可以在Xcopy中使用/ j开关,效果相同。
答案 5 :(得分:0)
我知道这个问题是11年前的,如今有robocopy可以替代xcopy。
您需要检查/ J选项
/J :: copy using unbuffered I/O (recommended for large files)