WriteFileEx 函数 (fileapi.h)
将数据写入指定的文件或输入/输出 (I/O) 设备。 它以异步方式报告其完成状态,并在写入已完成或取消并且调用线程处于可警报等待状态时调用指定的完成例程。
若要将数据同步写入文件或设备,请使用 WriteFile 函数。
语法
BOOL WriteFileEx(
[in] HANDLE hFile,
[in, optional] LPCVOID lpBuffer,
[in] DWORD nNumberOfBytesToWrite,
[in, out] LPOVERLAPPED lpOverlapped,
[in] LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
参数
[in] hFile
文件或 I/O 设备的句柄 (例如文件、文件流、物理磁盘、卷、控制台缓冲区、磁带驱动器、套接字、通信资源、mailslot 或管道) 。
此参数可以是 CreateFile 函数使用 FILE_FLAG_OVERLAPPED 标志打开的任何句柄,也可以是套接字或 accept 函数返回的套接字句柄。
不要将 I/O 完成端口与此句柄相关联。 有关详细信息,请参见“备注”部分。
此句柄还必须具有 GENERIC_WRITE 访问权限。 有关访问权限的详细信息,请参阅 文件安全和访问权限。
[in, optional] lpBuffer
指向缓冲区的指针,该缓冲区包含要写入文件或设备的数据。
此缓冲区必须在写入操作期间保持有效。 在完成写入操作之前,调用方不得使用此缓冲区。
[in] nNumberOfBytesToWrite
要写入文件或设备的字节数。
值为零指定 null 写入操作。 null 写入操作的行为取决于基础文件系统。
网络上的管道写入操作限制为每次写入 65,535 个字节。 有关管道的详细信息,请参阅“备注”部分。
[in, out] lpOverlapped
指向 OVERLAPPED 数据结构的指针,该结构提供在重叠 (异步) 写入操作期间使用的数据。
对于支持字节偏移量的文件,必须指定开始写入文件的字节偏移量。 可以通过设置 OVERLAPPED 结构的 Offset 和 OffsetHigh 成员来指定此偏移量。 对于不支持字节偏移的文件或设备, 将忽略 Offset 和 OffsetHigh 。
若要写入文件末尾,请将 OVERLAPPED 结构的 Offset 和 OffsetHigh 成员指定为 0xFFFFFFFF
。 这在功能上等效于之前调用 CreateFile 函数以使用FILE_APPEND_DATA访问打开 hFile。
WriteFileEx 函数忽略 OVERLAPPED 结构的 hEvent 成员。 应用程序可在 WriteFileEx 调用的上下文中出于自己的目的使用该成员。 WriteFileEx 通过调用或排队调用 lpCompletionRoutine 指向的完成例程来指示其写入操作完成,因此它不需要事件句柄。
WriteFileEx 函数确实使用 OVERLAPPED 结构的 Internal 和 InternalHigh 成员。 不应更改这些成员的值。
OVERLAPPED 数据结构必须在写入操作期间保持有效。 当写入操作等待完成时,它不应是可能超出范围的变量。
[in] lpCompletionRoutine
指向完成写入操作且调用线程处于可警报等待状态时调用的完成例程的指针。 有关此完成例程的详细信息,请参阅 FileIOCompletionRoutine。
返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。
如果 WriteFileEx 函数成功,则调用线程具有挂起的异步 I/O 操作:对文件的重叠写入操作。 当此 I/O 操作完成并且调用线程在可警报等待状态下被阻止时,操作系统将调用 lpCompletionRoutine 指向的 WAIT_IO_COMPLETION
函数,并且等待以 返回代码完成。
如果函数成功且文件写入操作完成,但调用线程未处于可警报等待状态,则系统将对 *lpCompletionRoutine 的调用排队,保持调用,直到调用线程进入可警报等待状态。 有关可发出警报的等待状态和重叠的输入/输出操作的详细信息,请参阅 关于同步。
注解
使用 WriteFileEx 时,应检查 GetLastError,即使函数返回“success”来检查成功但有一些你可能想要了解的结果的情况也是如此。 例如,调用 WriteFileEx 时缓冲区溢出将返回 TRUE
,但 GetLastError 将使用 报告溢出 ERROR_MORE_DATA
。 如果函数调用成功且没有警告条件, 则 GetLastError 将返回 ERROR_SUCCESS
。
如果 hFile 参数与 I/O 完成端口相关联,WriteFileEx 函数将失败。 若要使用此类型的句柄执行写入,请使用 WriteFile 函数。
如果存在太多未完成的异步 I/O 请求, WriteFileEx 函数可能会失败。 如果出现此类故障, GetLastError 可以返回 ERROR_INVALID_USER_BUFFER
或 ERROR_NOT_ENOUGH_MEMORY
。
若要取消所有挂起的异步 I/O 操作,请使用以下任一函数:
- CancelIo:此函数仅取消由指定文件句柄的调用线程发出的操作。
- CancelIoEx:此函数取消线程针对指定文件句柄发出的所有操作。
使用 CancelSynchronousIo 取消挂起的同步 I/O 操作。
取消的 I/O 操作已完成, ERROR_OPERATION_ABORTED错误。
如果 hFile 指定的文件的一部分被另一个进程锁定,并且指定的写入操作与锁定部分重叠, 则 WriteFileEx 将失败。
写入文件时,在关闭用于写入的所有句柄之前,最后一次写入时间不会完全更新。 因此,若要确保准确的上次写入时间,请在写入文件后立即关闭文件句柄。
在写入操作使用缓冲区时访问输出缓冲区可能会导致从该缓冲区写入的数据损坏。 在写入操作完成之前,应用程序不得写入、重新分配或释放写入操作正在使用的输出缓冲区。
请注意,可能无法为远程文件正确更新时间戳。 若要确保结果一致,请使用无缓冲区 I/O。
系统将要写入的零个字节解释为指定 null 写入操作, WriteFile 不会截断或扩展文件。 若要截断或扩展文件,请使用 SetEndOfFile 函数。
应用程序使用 WaitForSingleObjectEx、 WaitForMultipleObjectsEx、 MsgWaitForMultipleObjectsEx、 SignalObjectAndWait 和 SleepEx 函数进入可警报的等待状态。 有关可发出警报的等待状态和重叠 I/O 操作的详细信息,请参阅 关于同步。
如果直接写入具有已装载文件系统的卷,则必须先获取该卷的独占访问权限。 否则,可能会导致数据损坏或系统不稳定,因为应用程序的写入操作可能与来自文件系统的其他更改冲突,并使卷的内容处于不一致状态。 为防止这些问题,Windows Vista 及更高版本中进行了以下更改:
- 如果卷没有装载的文件系统,或者满足以下条件之一,则对卷句柄的写入将成功:
- 要写入的扇区是启动扇区。
- 要写入的扇区驻留在文件系统空间之外。
- 已使用 FSCTL_LOCK_VOLUME 或 FSCTL_DISMOUNT_VOLUME 显式锁定或卸载卷。
- 该卷没有实际的文件系统。 (换句话说,它具有 RAW 文件系统 mounted.)
- 如果满足以下条件之一,则磁盘句柄上的写入将成功:
- 要写入的扇区不在卷的范围内。
- 要写入的扇区位于已装载卷内,但已使用 FSCTL_LOCK_VOLUME 或 FSCTL_DISMOUNT_VOLUME 显式锁定或卸载卷。
- 要写入到的扇区位于没有除 RAW 以外的已装载文件系统的卷内。
使用 FILE_FLAG_NO_BUFFERING 成功处理使用 CreateFile 打开的文件有严格的要求。 有关详细信息,请参阅 文件缓冲。
在 Windows 8 和 Windows Server 2012 中,此函数由以下技术支持。
技术 | 支持 |
---|---|
服务器消息块 (SMB) 3.0 协议 | 是 |
SMB 3.0 透明故障转移 (TFO) | 是 |
具有横向扩展文件共享的 SMB 3.0 (SO) | 是 |
群集共享卷文件系统 (CSV) | 是 |
弹性文件系统 (ReFS) | 是 |
事务处理操作
如果存在绑定到句柄的事务,则会事务处理文件写入。 有关详细信息,请参阅 关于事务 NTFS。
示例
有关示例,请参阅 命名管道服务器使用完成例程。
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows XP [桌面应用 | UWP 应用] |
最低受支持的服务器 | Windows Server 2003 [桌面应用 | UWP 应用] |
目标平台 | Windows |
标头 | fileapi.h (包括 Windows.h) |
Library | Kernel32.lib |
DLL | Kernel32.dll |