有人知道一种将文件从路径A复制到路径B并抑制Windows文件系统缓存的方法吗?
通常的用途是将大文件从USB驱动器或服务器复制到本地计算机。 如果文件很大,Windows似乎会交换所有内容,例如 2GiB。
更喜欢用C#编写示例,但我想如果可能的话,这将是某种Win32调用。
在C#中,我发现类似的方法可以工作,可以将其更改为直接复制到目标文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| 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提高性能。
SUMMARY
There is a flag for CreateFile()
called FILE_FLAG_SEQUENTIAL_SCAN which
will direct the Cache Manager to
access the file sequentially.
Anyone reading potentially large files
with sequential access can specify
this flag for increased performance.
This flag is useful if you are reading
files that are"mostly" sequential,
but you occasionally skip over small
ranges of bytes.
如果您不介意使用工具,那么ESEUTIL对我来说很棒。
您可以检查此博客条目,以比较Buffered和NonBuffered 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)