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

发布于 2024-07-04 02:07:38 字数 161 浏览 14 评论 0原文

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

Anybody know of a way to copy a file from path A to path B and suppressing the Windows file system cache?
Typical use is copying a large file from a USB drive, or server to your local machine. Windows seems to swap everything out if the file is really big, e.g. 2GiB.
Prefer example in C#, but I'm guessing this would be a Win32 call of some sort if possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

牛↙奶布丁 2024-07-11 02:07:38

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

In C# I have found something like this to work, this can be changed to copy directly to destination file:

    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;
        }
    }
月下伊人醉 2024-07-11 02:07:38

我不确定这是否有帮助,但请查看 增加使用 FILE_FLAG_SEQUENTIAL_SCAN 的性能。

摘要

有一个 CreateFile() 标志
称为 FILE_FLAG_SEQUENTIAL_SCAN 其中
将指示缓存管理器
按顺序访问文件。

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

I am not sure if this helps, but take a look at Increased Performance Using 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.

白芷 2024-07-11 02:07:38

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

MSDN 有一篇关于它们的好文章:http://support.microsoft.com/kb/99794

Even more important, there are FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING.

MSDN has a nice article on them both: http://support.microsoft.com/kb/99794

ら栖息 2024-07-11 02:07:38

Eseutil是一个正确的答案,同样从Win7 / 2008 R2开始,您可以在Xcopy中使用/j开关,它具有相同的效果。

Eseutil is a correct answer, also since Win7 / 2008 R2, you can use the /j switch in Xcopy, which has the same effect.

野味少女 2024-07-11 02:07:38

我知道这个问题是 11 年前的问题,现在有 robocopy,它是 xcopy 的替代品。

你需要检查 /J 选项
/J :: 使用无缓冲 I/O 进行复制(推荐用于大文件)

I understand this question was 11 years ago, nowadays there is robocopy which is kind of replacement for xcopy.

you need to check /J option
/J :: copy using unbuffered I/O (recommended for large files)

極樂鬼 2024-07-11 02:07:38

如果您不介意使用工具,ESEUTIL 对我来说非常有用。

您可以查看此博客 条目比较 Buffered 和 NonBuffered IO 函数以及从何处获取 ESEUTIL。

从 technet 博客复制一些文本:

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

If you dont mind using a tool, ESEUTIL worked great for me.

You can check out this blog entry comparing Buffered and NonBuffered IO functions and from where to get ESEUTIL.

copying some text from the technet blog:

So looking at the definition of buffered I/O above, we can see where the perceived performance problems lie - in the file system cache overhead. Unbuffered I/O (or a raw file copy) is preferred when attempting to copy a large file from one location to another when we do not intend to access the source file after the copy is complete. This will avoid the file system cache overhead and prevent the file system cache from being effectively flushed by the large file data. Many applications accomplish this by calling CreateFile() to create an empty destination file, then using the ReadFile() and WriteFile() functions to transfer the data.
CreateFile() - The CreateFile function creates or opens a file, file stream, directory, physical disk, volume, console buffer, tape drive, communications resource, mailslot, or named pipe. The function returns a handle that can be used to access an object.
ReadFile() - The ReadFile function reads data from a file, and starts at the position that the file pointer indicates. You can use this function for both synchronous and asynchronous operations.
WriteFile() - The WriteFile function writes data to a file at the position specified by the file pointer. This function is designed for both synchronous and asynchronous operation.
For copying files around the network that are very large, my copy utility of choice is ESEUTIL which is one of the database utilities provided with Exchange.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文