平台 SDK: 文件存储

WriteFile

WriteFile函数将数据写入文件,并为同步和异步操作而设计。 该功能开始将数据写入文件指针指定位置的文件。 写操作完成后,文件指针会根据实际写入的字节数进行调整,但使用FILE_FLAG_OVERLAPPED打开文件时除外。 如果文件句柄是为重叠的输入和输出(I / O)创建的,则应用程序必须在写入操作完成后调整文件指针的位置。

该功能专为同步和异步操作而设计。 WriteFileEx函数仅用于异步操作。 它允许应用程序在文件写入操作期间执行其他处理。

BOOL WriteFile(
  HANDLE hFile,                    // 文件句柄
  LPCVOID lpBuffer,                // 数据缓冲区
  DWORD nNumberOfBytesToWrite,     // 要写入的字节数
  LPDWORD lpNumberOfBytesWritten,  // 写入的字节数
  LPOVERLAPPED lpOverlapped        // 重叠缓冲区
);

参数

  • hFile

  • [in] 要写入的文件句柄。 文件句柄必须已经通过GENERIC_WRITE访问文件来创建。

    Windows NT/2000/XP: 对于异步写入操作,hFile可以是由CreateFile函数使用FILE_FLAG_OVERLAPPED标志打开的任何句柄,也可以是由套接字或accept函数返回的套接字句柄。

    Windows 95/98/Me: 对于异步写操作,hFile可以是通过CreateFile使用FILE_FLAG_OVERLAPPED标志打开的通信资源,也可以是由socket或accept返回的套接字句柄。 您不能对邮件槽,命名管道或磁盘文件执行异步写入操作。

  • lpBuffer

  • [in] 指向包含要写入文件的数据的缓冲区的指针。

  • nNumberOfBytesToWrite

  • [in] 指定要写入文件的字节数。

    零值指定空写入操作。 空写操作的行为取决于底层文件系统。 要截断或扩展文件,请使用SetEndOfFile函数。

    命名管道写操作通过网络限制为65,535字节。

  • lpNumberOfBytesWritten

  • [out] 指向接收写入字节数的变量的指针。 在执行任何工作或错误检查之前,WriteFile将此值设置为零。

    Windows NT/2000/XP: 如果lpOverlapped为NULL,则lpNumberOfBytesWritten不能为NULL。 如果lpOverlapped不为NULL,则lpNumberOfBytesWritten可以为NULL。 如果这是一个重叠的写入操作,则可以通过调用GetOverlappedResult来获取写入的字节数。 如果hFile与I / O完成端口关联,则可以通过调用GetQueuedCompletionStatus来获取写入的字节数。

    如果使用I / O完成端口,并且您使用回调例程释放分配给由lpOverlapped参数指向的OVERLAPPED结构的内存,则请指定NULL作为此参数的值,以避免解除分配期间的内存损坏问题。 此内存损坏问题将导致此参数中返回无效的字节数。

    Windows 95/98/Me: 该参数不能为NULL。

  • lpOverlapped

  • [in] 指向OVERLAPPED结构的指针。 如果使用FILE_FLAG_OVERLAPPED打开hFile,则需要此结构。

    如果用FILE_FLAG_OVERLAPPED打开hFile,则lpOverlapped参数不能为NULL。 它必须指向一个有效的OVERLAPPED结构。 如果用FILE_FLAG_OVERLAPPED打开hFile,并且lpOverlapped为NULL,则该函数可能会错误地报告写入操作已完成。

    如果使用FILE_FLAG_OVERLAPPED打开hFile并且lpOverlapped不为NULL,则写操作从OVERLAPPED结构中指定的偏移量开始,并且在写操作完成之前WriteFile可能会返回。 在这种情况下,WriteFile返回FALSE,并且GetLastError函数返回ERROR_IO_PENDING。 这允许调用进程在写操作完成时继续处理。 写操作完成后,OVERLAPPED结构中指定的事件被设置为已发信号状态。

    如果未使用FILE_FLAG_OVERLAPPED打开hFile,并且lpOverlapped为NULL,则写入操作从当前文件位置开始,WriteFile不会返回,直到操作完成。

    当它开始I / O操作时,WriteFile将由OVERLAPPED结构的hEvent成员指定的事件重置为非信号状态。 因此,呼叫者不需要这样做。

    Windows NT/2000/XP: 如果未使用FILE_FLAG_OVERLAPPED打开hFile,并且lpOverlapped不为NULL,则写操作从OVERLAPPED结构中指定的偏移量开始,WriteFile在写操作完成之前不会返回。

    Windows 95/98/Me: 对于文件,磁盘,管道或邮件槽的操作,此参数必须为NULL; 指向OVERLAPPED结构的指针会导致调用失败。 但是,Windows 95/98 / Me支持串行和并行端口上的重叠I / O。

返回值

如果函数成功,返回值为非零。

如果函数失败,返回值为零。 要获得扩展的错误信息,请调用GetLastError。

备注

请注意,时间戳可能无法正确更新远程文件。 为确保一致的结果,请使用无缓冲的I / O。 使用FILE_FLAG_NO_BUFFERING打开的文件时,应用程序必须满足某些要求:

  • 文件访问必须以文件内的字节偏移量开始,这些偏移量是卷的扇区大小的整数倍。 要确定卷的扇区大小,请调用GetDiskFreeSpace函数。

  • 文件访问权限必须是卷的扇区大小整数倍的字节数。 例如,如果扇区大小为512字节,则应用程序可以请求读取和写入512,1024或2048字节,但不是335,981或7171字节。

  • 读取和写入操作的缓冲区地址必须是扇区对齐的(在内存中的地址是卷的扇区大小的整数倍)。 扇区对齐缓冲区的一种方法是使用VirtualAlloc函数来分配缓冲区。 此函数分配与系统页面大小整数倍的地址对齐的内存。 由于页面和扇区扇区大小都是2的幂,因此系统页面大小的倍数对齐的内存也按卷的扇区大小的倍数对齐。

如果部分文件被另一个进程锁定,并且写入操作与被锁定部分重叠,则该功能失败。

在写操作正在使用缓冲区时访问输出缓冲区可能会导致从该缓冲区写入的数据被破坏。 应用程序不得写入,重新分配或释放写入操作正在使用的输出缓冲区,直到写入操作完成。

可以使用WriteFile和控制台输出的句柄将字符写入屏幕缓冲区。 该功能的确切行为由控制台模式决定。 数据写入当前光标位置。 写入操作后更新光标位置。

系统将零字节解释为指定空写入操作,并且WriteFile不截断或扩展文件。 要截断或扩展文件,请使用SetEndOfFile函数。

当写入缓冲区空间不足的非阻塞字节模式管道句柄时,WriteFile将返回TRUE,并带* lpNumberOfBytesWritten <nNumberOfBytesToWrite。

当应用程序使用WriteFile函数写入管道时,如果管道缓冲区已满,写入操作可能无法完成。 当读操作(使用ReadFile函数)使更多的缓冲区空间可用时,写操作完成。

如果匿名读取管道句柄已关闭且WriteFile尝试使用相应的匿名写入管道句柄进行写入,则该函数返回FALSE,并且GetLastError返回ERROR_BROKEN_PIPE。

每当有太多未完成的异步I / O请求时,WriteFile函数可能会因ERROR_INVALID_USER_BUFFER或ERROR_NOT_ENOUGH_MEMORY而失败。

要取消所有挂起的异步I / O操作,请使用CancelIo函数。 此函数仅取消指定文件句柄的调用线程发出的操作。 取消的I / O操作完成,并显示错误ERROR_OPERATION_ABORTED。

如果您试图写入没有软盘的软盘驱动器,系统会显示一个消息框,提示用户重试该操作。 为防止系统显示此消息框,请使用SEM_NOOPENFILEERRORBOX调用SetErrorMode函数。

示例代码

有关示例,请参阅读取,写入和锁定文件。

要求

  Windows NT/2000/XP: 包含在Windows NT 3.1和更高版本中。

  Windows 95/98/Me: 包含在Windows 95和更高版本中。

  头文件: 声明于 Winbase.h; 包含于  Windows.h.
  库: 使用Kernel32.lib.