如何在无缓冲模式下执行 CopyFile?

The Old New Thing (Raymond Chen) 工具

摘要

说明了如何将 COPY_FILE_NO_BUFFERING 标志与 CopyFileEx 和 CopyFile2 一起使用,以使用无缓冲句柄复制文件,以及为什么在句柄打开后无法使用进度回调来更改缓冲模式。

<p>一位客户正在使用 <code>Copy­File</code> 复制文件,但他们希望文件句柄以 <code>FILE_<wbr />FLAG_<wbr />NO_<wbr />BUFFERING</code> 方式打开。</p> <p>我们之前看到过 <a title="如何进行 CopyFile,但在目标句柄关闭之前刷新文件缓冲区?" href="https://devblogs.microsoft.com/oldnewthing/20221007-00/?p=107261">可以使用进度回调来让 <code>CopyFileEx</code> 或 <code>CopyFile2</code> 刷新输出句柄</a>。也许我们可以使用进度回调来以无缓冲方式打开句柄?</p> <p>不,这行不通,因为进度回调给你的是已经打开的句柄。你无法在事后更改它的缓冲标志。</p> <p>但这没关系,因为 <code>CopyFileEx</code> 和 <code>CopyFile2</code> 也有一个 flags 参数,其中一个标志是 <code>COPY_<wbr />FILE_<wbr />NO_<wbr />BUFFERING</code>,这意味着句柄应该以 <code>FILE_<wbr />FLAG_<wbr />NO_<wbr />BUFFERING</code> 打开。</p> <pre>BOOL success = CopyFileEx( sourceFilePath, destinationFilePath, nullptr, nullptr, nullptr, COPY_FILE_NO_BUFFERING); </pre> <p>你也可以用 <code>CopyFile2</code> 做同样的事情,但标志位于 options 结构体中。</p> <pre>COPYFILE2_EXTENDED_PARAMETERS parameters{}; parameters.dwSize = sizeof(parameters); parameters.dwCopyFlags = COPY_FILE_NO_BUFFERING; HRESULT hr = CopyFile2(sourceFilePath, destinationFilePath, &amp;parameters); </pre> <p>本文《<a href="https://devblogs.microsoft.com/oldnewthing/20260810-00/?p=112600">如何以无缓冲模式执行 CopyFile?</a>》最早出现在 <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a> 上。</p>
查看原文
查看缓存全文

缓存时间: 2026/08/12 08:26

# 如何以非缓冲模式执行 Copy­File? - The Old New Thing 来源:https://devblogs.microsoft.com/oldnewthing/20260810-00?p=112600 有一位客户正在使用 `Copy­File` 复制文件,但他们希望文件句柄以 `FILE\_FLAG\_NO\_BUFFERING` 方式打开。 我们在不久前看到,你可以使用 `Copy­File­Ex` 或 `Copy­File2` 的进度回调来刷新输出句柄(https://devblogs.microsoft.com/oldnewthing/20221007-00/?p=107261)。也许我们可以利用进度回调以非缓冲方式打开句柄? 不行,这行不通,因为进度回调提供给你的是已经打开的句柄。你无法在事后更改它的缓冲标志。 不过没关系,因为 `Copy­File­Ex` 和 `Copy­File2` 也有一个标志参数,其中有一个标志就是 `COPY\_FILE\_NO\_BUFFERING`,它表示句柄应以 `FILE\_FLAG\_NO\_BUFFERING` 方式打开。 `` BOOL success = CopyFileEx( sourceFilePath, destinationFilePath, nullptr, nullptr, nullptr, COPY_FILE_NO_BUFFERING); `` 使用 `Copy­File2` 也可以达到同样的目的,但标志需要放在选项结构中。 `` COPYFILE2_EXTENDED_PARAMETERS parameters{}; parameters.dwSize = sizeof(parameters); parameters.dwCopyFlags = COPY_FILE_NO_BUFFERING; HRESULT hr = CopyFile2(sourceFilePath, destinationFilePath, &parameters); `` ### 分类 ### 主题 ## 作者 Raymond Chen Raymond 参与 Windows 的发展已有 30 多年。2003 年,他创办了一个名为 The Old New Thing 的网站,其受欢迎程度远远超出他最狂野的想象,这一发展至今仍让他心生畏惧。该网站还催生了一本书,书名巧合地也叫 The Old New Thing(Addison Wesley 2007 年出版)。他偶尔会出现在 Windows Dev Docs 的 Twitter 账号上,讲述一些不传达有用信息的故事。

相似文章

Go中的零拷贝: sendfile、splice 以及 io.Copy 的成本

Hacker News Top

本文解释了Go的io.Copy如何自动使用sendfile和splice进行TCP上的零拷贝文件传输,并展示了将文件包装成普通的io.Reader(例如用于日志记录)会悄然禁用此优化,导致性能显著下降。基准测试和strace输出说明了这种影响。

std::function 与 copyable_function 的互转换

Lobsters Hottest

对 C++26 中 std::function 和 std::copyable_function 之间互转换的技术分析,讨论了实现方法和性能权衡,并特别指出 libstdc++ 目前采用了一种较次优的方法。

为Windows 3.1改造WM_COPY­DATA消息

The Old New Thing (Raymond Chen)

本文解释如何利用共享地址空间,将针对32位Windows引入的WM_COPYDATA消息改造到16位Windows 3.1上,使得16位程序间的通信无需任何更改。

如何告知Windows我正在写入二进制文件?

The Old New Thing (Raymond Chen)

本文解释了Windows在操作系统层面并没有内置二进制与文本模式的概念;这种区别是由运行时库(如C运行时)处理的。它澄清了Windows将所有文件视为字节,内容转换必须手动执行或通过库来完成。