原文链接 -> 传送门
函数功能:
WriteFile 函数用于将数据写入指定的文件或输入/输出(I/O)设备。
此函数用于同步和异步操作。 对于专为异步操作设计的类似函数,请参见 WriteFileEx 函数。
API 函数原型:
注释:_In_ 说明该参数是输入的,_Out_ 说明该参数是输出的,_opt_ 说明该参数是可选的。
BOOL WINAPI WriteFile( _In_ HANDLE hFile, _In_ LPCVOID lpBuffer, _In_ DWORD nNumberOfBytesToWrite, _Out_opt_ LPDWORD lpNumberOfBytesWritten, _Inout_opt_ LPOVERLAPPED lpOverlapped );
参数解析:
|
参数 |
含义 |
|
hFile |
1. 指向文件或者 I/O 设备的句柄(例如:文件、文件流、文件夹、物理磁盘、磁盘驱动器、控制台程序缓冲区、磁带驱动器、套接字、通信资源、邮槽和管道) |
|
lpBuffer |
1. 指向存放待写入文件或设备的数据缓冲区指针 |
|
nNumberOfBytesToWrite |
1. 待写入文件或设备数据字节数 |
|
lpNumberOfBytesWritten |
1. 指向接收使用同步 hFile 参数写入的字节数的变量指针。在检查工作或排查错误之前,WriteFile 函数将此值设置为 0。 如果这是异步操作,请为此参数使用 NULL,以避免潜在的错误结果 |
|
lpOverlapped |
1. 如果使用 FILE_FLAG_OVERLAPPED 打开 hFile 参数指向的文件或设备,则需要指向OVERLAPPED 结构的指针,否则此参数可以为 NULL |
返回值:
1. 如果函数调用成功,返回值为非 0(TRUE);
2. 如果函数调用失败或异步操作未完成,则返回值为 0(FALSE)。
获取有关错误的更多信息,请调用 GetLastError 函数。
注:GetLastError 函数的代码 ERROR_IO_PENDING 不是失败;它表示写操作正等待异步完成。 有关详细信息,请参阅备注。
备注:
1. 当出现以下情况之一时,WriteFile 函数返回:
· 请求的字节数被写入
· 当读操作读取到管道末,函数释放管道缓冲区空间(如果写入被阻塞),有关详细信息,请参阅管道部分
· 异步句柄正在使用,又异步进行写操作
· 发生错误
2. 每当有太多未完成的异步 I/O 请求时,WriteFile 函数可能会执行失败,出现 ERROR_INVALID_USER_BUFFER 或 ERROR_NOT_ENOUGH_MEMORY 错误。
3. 要取消所有待处理的异步 I/O 操作,请使用其中一个:
CancelIo - 此函数仅取消由指定文件句柄的当前线程发出的操作。
CancelIoEx - 此函数取消由指定文件句柄的全部线程发出的所有操作。
4. 使用 CancelSynchronousIo 函数取消挂起的同步 I/O 操作。
5. 取消的 I/O 操作以错误代码 ERROR_OPERATION_ABORTED 完成。
6. WriteFile 函数可能会以错误 ERROR_NOT_ENOUGH_QUOTA 失败,这意味着调用进程的缓冲区不能被页面锁定。 更多信息,请参阅 SetProcessWorkingSetSize 函数。
7. 如果文件的一部分被另一进程锁定,并且写入被锁定的部分,WriteFile 函数将调用失败。
8. 当写入文件时,最后写入时间不会完全更新,直到用于写入的所有句柄都已关闭。 因此,为了确保最后的写入时间准确,在写入文件后应立即关闭文件句柄。
9. 在写入操作正在使用缓冲区时访问输出缓冲区可能导致从该缓冲区写入的数据损坏。 直到写入操作完成,应用程序不得对写操作使用的输出缓冲区进行写入,重新分配或释放。 当使用异步文件句柄时,这可能是特别容易出问题。 有关同步和异步文件句柄的其他信息,请参见后面的同步和文件位置部分以及同步和异步 I/O 。
10. 请注意,对于远程文件,时间戳可能无法正确更新。 为了确保一致的结果,请使用无缓冲的 I/O。
11. 系统将零字节解释为指定空写操作,WriteFile 函数不截短或扩展该文件。 要截短或扩展文件,请使用 SetEndOfFile函数。
12. 字符可以使用带有控制台输出句柄的 WriteFile 函数写入屏幕缓冲区。 该函数的确切行为由控制台模式决定。 数据被写入当前光标位置。 在写操作之后更新光标位置。 有关控制台句柄的更多信息,请参阅 CreateFile。
13. 当写入通信设备时,WriteFile 函数的行为是由 SetCommTimeouts 和 GetCommTimeouts 函数设置和获取的当前通信超时来确定。 如果未能设置超时值,则可能会发生不可预测的结果。 有关通信超时的更多信息,请参见COMMTIMEOUTS 结构。
14. 虽然单扇区写入是原子的,但是除非使用事务(即,创建的句柄是事务句柄;例如,使用 CreateFileTransacted 函数创建的句柄),否则多扇区写不能保证是原子的。被缓存的多扇区写入可能不总是立即写入磁盘; 因此,在 CreateFile 中指定 FILE_FLAG_WRITE_THROUGH ,以确保将整个多扇区写入被写入磁盘,而不会出现潜在的缓存延迟。
15. 如果直接写入具有已装入文件系统的磁盘驱动器,则必须首先获得对磁盘驱动器的独占访问权限。否则,可能会导致数据损坏或系统不稳定,因为应用程序的写入可能与来自文件系统的其他更改冲突,并使磁盘驱动器的内容处于不一致状态。为了防止出现这些问题,在 Windows Vista 及更高版本的 Windows 中进行了以下更改:
a. 如果磁盘驱动器没有已装入的文件系统,或者满足以下条件之一,则对磁盘驱动器句柄的写入将成功:
· 要写入的扇区是引导扇区
· 要写入的扇区驻留在文件系统空间之外
· 您已使用 FSCTL_LOCK_VOLUME 或 FSCTL_DISMOUNT_VOLUME 明确锁定或卸载磁盘驱动器
· 卷没有实际的文件系统 (换句话说,它已经安装了一个 RAW 文件系统)
b. 如果满足以下条件之一,则磁盘句柄上的写入将成功:
· 要写入的扇区不在卷的范围内
· 要写入的扇区位于已安装的磁盘驱动器中,但已使用 FSCTL_LOCK_VOLUME 或 FSCTL_DISMOUNT_VOLUME 明确锁定或卸载磁盘驱动器
· 要写入的扇区位于没有装入除 RAW 以外的文件系统的磁盘驱动器内
16. 处理对使用 FILE_FLAG_NO_BUFFERING 通过 CreateFile 打开的文件有严格的要求。 有关详细信息,请参阅 File Buffering。
17. 如果使用 FILE_FLAG_OVERLAPPED 打开 hFile 参数指向的文件或设备,则以下条件有效:
· lpOverlapped 参数必须指向有效且唯一的 OVERLAPPED 结构,否则函数可能会不正确地报告写操作完成
· lpNumberOfBytesWritten 参数应设置为 NULL。 要获取写入的字节数,请使用 GetOverlappedResult 函数。 如果 hFile 参数与 I/O 完成端口相关联,您还可以通过调用 GetQueuedCompletionStatus 函数获取写入的字节数
18. 在Windows Server 2012 中,以下技术支持此函数:
|
技术 |
支持 |
|
Server Message Block (SMB) 3.0 protocol |
是 |
|
SMB 3.0 Transparent Failover (TFO) |
是 |
|
SMB 3.0 with Scale-out File Shares (SO) |
是 |
|
Cluster Shared Volume File System (CsvFS) |
是 |
|
Resilient File System (ReFS) |
是 |
同步和文件位置
19. 如果 hFile 参数指向的文件或设备使用 FILE_FLAG_OVERLAPPED 打开,则它是一个异步文件句柄; 否则为同步。 如前所述,使用 OVERLAPPED 结构的规则对每个结构略有不同。
注:如果打开了文件或设备为异步写入读取 ,则使用该句柄对 WriteFile 等函数的后续调用通常立即返回,但也可以与被阻止的同步执行。 有关详细信息,请参阅 http://support.microsoft.com/kb/156932。
20. 使用异步文件句柄的注意事项:
a. WriteFile 函数可能在写操作完成之前返回。在这种情况下,WriteFile 函数返回 FALSE,并且 GetLastError 函数返回 ERROR_IO_PENDING,这允许调用进程在系统完成写操作时继续。
b. lpOverlapped 参数不能为 NULL,应考虑以下情况:
· 尽管 OVERLAPPED 结构中指定的事件由系统自动设置和重置,但是 OVERLAPPED 结构中指定的偏移量不会自动更新
· WriteFile 函数在开始 I/O 操作时将事件重置为非信号状态
· OVERLAPPED 结构中指定的事件在写操作完成时设置为信号状态;直到那时,写操作才会被认为是待处理的
· 因为写操作在 OVERLAPPED 结构中指定的偏移处开始,并且 WriteFile 函数可能在系统级写操作完成之前返回(写入挂起),所以结构的偏移和任何其他部分都不应被修改,释放,或由应用程序重用,直到发出事件信号(即写入完成)
21. 使用同步文件句柄的注意事项:
· 如果 lpOverlapped 为 NULL,则写操作从当前文件位置开始,除非操作完成,否则 WriteFile 函数不返回,并且系统在 WriteFile 函数返回之前更新文件指针
· 如果 lpOverlapped 不为 NULL,写操作将从 OVERLAPPED 结构中指定的偏移量开始,除非操作完成,否则 WriteFile 函数不返回。 在 WriteFile 函数返回之前,系统会更新 OVERLAPPED 偏移量
22. 有关更多信息,请参见 CreateFile 和 Synchronous and Asynchronous I/O。
管道
23. 如果使用匿名管道并且读取句柄已关闭,则当 WriteFile 函数尝试使用管道的对应写入句柄写入时,函数返回 FALSE,GetLastError 函数返回 ERROR_BROKEN_PIPE。
24. 如果应用程序使用 WriteFile 函数写入管道时管道缓冲区已满,则写入操作可能无法立即完成。 当读操作(使用 ReadFile 函数)使更多的系统缓冲区可用于管道时,写操作将完成。
25. 当非阻塞,字节模式管道句柄写入缓冲区空间不足时,WriteFile 返回 TRUE 且 *lpNumberOfBytesWritten < nNumberOfBytesToWrite。
26. 有关管道的更多信息,请参阅 Pipes 。
事务操作
27. 如果有一个事务绑定到文件句柄,那么将处理文件写入。 有关详细信息,请参阅关于 NTFS 的事务。
例子:
有关示例,请参阅 Creating and Using a Temporary File 和 Opening a File for Reading or Writing。
以下 C++ 示例显示如何对齐扇区以进行无缓冲文件写入。 Size 变量是写入文件的原始数据块的大小。 更多无缓冲文件 I / O 的其他规则,请参阅 File Buffering。
#include#define ROUND_UP_SIZE(Value,Pow2) ((SIZE_T) ((((ULONG)(Value)) + (Pow2) - 1) & (~(((LONG)(Pow2)) - 1)))) #define ROUND_UP_PTR(Ptr,Pow2) ((void *) ((((ULONG_PTR)(Ptr)) + (Pow2) - 1) & (~(((LONG_PTR)(Pow2)) - 1)))) void main() { // Function code DWORD BytesPerSector = 0; // obtained from the GetFreeDiskSpace function. DWORD Size = 0; // buffer size of your data to write // ... obtain data here // sample data BytesPerSector = 65536; Size = 15536; // // Ensure you have one more sector than Size would require. SIZE_T SizeNeeded = BytesPerSector + ROUND_UP_SIZE(Size, BytesPerSector); // Replace this statement with any allocation routine. LPBYTE Buffer = (LPBYTE) malloc(SizeNeeded); // Error checking of your choice. if ( !Buffer ) { goto cleanup; } // Actual alignment happens here. void * BufferAligned = ROUND_UP_PTR(Buffer, BytesPerSector); // Add code using BufferAligned here. cleanup: if ( Buffer ) { // Replace with corresponding free routine. free(Buffer); } }
需求:
|
Minimum supported client |
Windows XP [桌面应用程序 | Windows 商店应用程序] |
|
Minimum supported server |
Windows 2003 服务器版 [桌面应用程序 | Windows 商店应用程序] |
|
Minimum supported phone |
Windows Phone 8 |
|
Header |
FileAPI.h (包含于 Windows.h); |
|
Library |
Kernel32.lib |
|
DLL |
Kernel32.dll |




