ReadFile 函数 (fileapi.h)
从指定的文件或输入/输出 (I/O) 设备读取数据。 读取发生在文件指针指定的位置(如果设备支持)。
此函数适用于同步和异步操作。 有关专为异步操作设计的类似函数,请参阅 ReadFileEx。
语法
BOOL ReadFile(
[in] HANDLE hFile,
[out] LPVOID lpBuffer,
[in] DWORD nNumberOfBytesToRead,
[out, optional] LPDWORD lpNumberOfBytesRead,
[in, out, optional] LPOVERLAPPED lpOverlapped
);
参数
[in] hFile
设备的句柄 (例如文件、文件流、物理磁盘、卷、控制台缓冲区、磁带驱动器、套接字、通信资源、mailslot 或管道) 。
必须已创建具有读取访问权限 的 hFile 参数。 有关详细信息,请参阅 通用访问权限 和 文件安全性和访问权限。
对于异步读取操作,hFile 可以是 CreateFile 函数使用 FILE_FLAG_OVERLAPPED 标志打开的任何句柄,也可以是套接字或 accept 函数返回的套接字句柄。
[out] lpBuffer
指向接收从文件或设备读取的数据的缓冲区的指针。
此缓冲区必须在读取操作期间保持有效。 在完成读取操作之前,调用方不得使用此缓冲区。
[in] nNumberOfBytesToRead
要读取的最多字节数。
[out, optional] lpNumberOfBytesRead
指向变量的指针,该变量接收在使用同步 hFile 参数时读取的字节数。 ReadFile 在执行任何工作或错误检查之前将此值设置为零。 如果这是异步操作,请对此参数使用 NULL ,以避免潜在的错误结果。
仅当 lpOverlapped 参数不为 NULL 时,此参数才能为 NULL。
Windows 7: 此参数不能为 NULL。
有关详细信息,请参见“备注”部分。
[in, out, optional] lpOverlapped
如果使用 FILE_FLAG_OVERLAPPED 打开 hFile 参数,则需要指向 OVERLAPPED 结构的指针,否则可为 NULL。
如果使用 FILE_FLAG_OVERLAPPED 打开 hFile,则 lpOverlapped 参数必须指向有效且唯一的 OVERLAPPED 结构,否则函数可能会错误地报告读取操作已完成。
对于支持字节偏移量的 hFile ,如果使用此参数,则必须指定从文件或设备开始读取的字节偏移量。 此偏移量是通过设置 OVERLAPPED 结构的 Offset 和 OffsetHigh 成员指定的。 对于不支持字节偏移量的 hFile , 将忽略 Offset 和 OffsetHigh 。
有关 lpOverlapped 和 FILE_FLAG_OVERLAPPED的不同组合的详细信息,请参阅“备注”部分和 “同步和文件位置” 部分。
返回值
如果函数成功,则返回值为非零 (TRUE) 。
如果函数失败或正在异步完成,则返回值为零 (FALSE) 。 若要获得更多的错误信息,请调用 GetLastError 函数。
注解
发生以下情况之一时, ReadFile 函数将返回 :
- 读取请求的字节数。
- 写入操作在管道的写入端完成。
- 正在使用异步句柄,并且读取正在异步进行。
- 发生错误。
每当存在过多的未完成异步 I/O 请求时,ReadFile 函数可能会失败并出现ERROR_INVALID_USER_BUFFER或ERROR_NOT_ENOUGH_MEMORY。
若要取消所有挂起的异步 I/O 操作,请使用以下任一函数:
- CancelIo - 此函数仅取消由指定文件句柄的调用线程发出的操作。
- CancelIoEx - 此函数取消由指定文件句柄的线程发出的所有操作。
使用 CancelSynchronousIo 取消挂起的同步 I/O 操作。
取消的 I/O 操作已完成, ERROR_OPERATION_ABORTED错误。
ReadFile 函数可能会失败并ERROR_NOT_ENOUGH_QUOTA,这意味着调用进程的缓冲区无法锁定页。 有关详细信息,请参阅 SetProcessWorkingSetSize。
如果文件的一部分被另一个进程锁定,并且读取操作与锁定部分重叠,则此函数将失败。
在读取操作使用缓冲区时访问输入缓冲区可能会导致读取到该缓冲区的数据损坏。 在读取操作完成之前,应用程序不得读取、写入、重新分配或释放读取操作正在使用的输入缓冲区。 使用异步文件句柄时,这可能会特别出现问题。 有关同步文件句柄与异步文件句柄的其他信息,请参阅 同步和文件位置 部分以及 CreateFile 参考主题。
可以使用具有控制台输入句柄的 ReadFile 从控制台输入缓冲区读取字符。 控制台模式确定 ReadFile 函数的确切行为。 默认情况下,控制台模式 为ENABLE_LINE_INPUT,指示 ReadFile 应在到达回车符之前读取。 如果按 Ctrl+C,调用成功,但 GetLastError 返回 ERROR_OPERATION_ABORTED。 有关详细信息,请参阅 CreateFile。
从通信设备读取时,ReadFile 的行为由当前通信超时确定,该超时是使用 SetCommTimeouts 和 GetCommTimeouts 函数设置和检索的。 如果未能设置超时值,可能会出现不可预知的结果。 有关通信超时的详细信息,请参阅 COMMTIMEOUTS。
如果 ReadFile 尝试从缓冲区太小的 mailslot 读取,则函数返回 FALSE , GetLastError 返回 ERROR_INSUFFICIENT_BUFFER。
成功处理使用 FILE_FLAG_NO_BUFFERING 标志通过CreateFile 打开的文件有严格的要求。 有关详细信息,请参阅 文件缓冲。
如果使用 FILE_FLAG_OVERLAPPED 打开 hFile,则以下条件有效:
- lpOverlapped 参数必须指向有效且唯一的 OVERLAPPED 结构,否则函数可能会错误地报告读取操作已完成。
- lpNumberOfBytesRead 参数应设置为 NULL。 使用 GetOverlappedResult 函数获取实际读取的字节数。 如果 hFile 参数与 I/O 完成端口相关联,则还可以通过调用 GetQueuedCompletionStatus 函数获取读取的字节数。
同步和文件位置
如果使用 FILE_FLAG_OVERLAPPED 打开 hFile,则它是异步文件句柄;否则,它是同步的。 如前所述,每个使用 OVERLAPPED 结构的规则略有不同。- ReadFile 可能会在读取操作完成之前返回。 在此方案中, ReadFile 返回 FALSE , GetLastError 函数返回 ERROR_IO_PENDING,这允许调用进程在系统完成读取操作时继续。
- lpOverlapped 参数不能为 NULL,并且应考虑到以下事实:
- 尽管在 OVERLAPPED 结构中指定的事件由系统自动设置和重置,但在 OVERLAPPED 结构中指定的偏移量不会自动更新。
- ReadFile 在开始 I/O 操作时将事件重置为未签名状态。
- 当读取操作完成时, 在 OVERLAPPED 结构中指定的事件将设置为信号状态;在该时间之前,读取操作被视为挂起。
- 由于读取操作从 OVERLAPPED 结构中指定的偏移量开始,并且 ReadFile 可能在系统级读取操作完成之前返回, (读取挂起) ,因此,在向事件 (发出信号之前,应用程序不应修改、释放或重复使用该偏移量或结构的任何其他部分, 读取) 完成。
- 如果在异步操作期间检测到文件结尾 (EOF) ,则调用该操作的 GetOverlappedResult 将返回 FALSE , GetLastError 返回 ERROR_HANDLE_EOF。
- 如果 lpOverlapped 为 NULL,则读取操作从当前文件位置开始, ReadFile 在操作完成之前不会返回,并且系统会在 ReadFile 返回之前更新文件指针。
- 如果 lpOverlapped 不为 NULL,则读取操作从 OVERLAPPED 结构中指定的偏移量开始, ReadFile 在读取操作完成之前不会返回。 在 ReadFile 返回之前,系统将更新 OVERLAPPED 偏移量和文件指针。
- 如果 lpOverlapped 为 NULL,则当同步读取操作到达文件末尾时, ReadFile 将返回 TRUE 并将 设置为
*lpNumberOfBytesRead
零。 - 如果 lpOverlapped 不为 NULL,则当同步读取操作到达文件末尾时, ReadFile 返回 FALSE , GetLastError 返回 ERROR_HANDLE_EOF。
管道
如果使用匿名管道且写入句柄已关闭,则 当 ReadFile 尝试使用管道的相应读取句柄进行读取时,函数返回 FALSE , GetLastError 返回 ERROR_BROKEN_PIPE。如果在消息模式下读取命名管道,并且下一条消息的长度超过 nNumberOfBytesToRead 参数指定的时间, 则 ReadFile 返回 FALSE , GetLastError 返回 ERROR_MORE_DATA。 消息的其余部分可以通过后续调用 ReadFile 或 PeekNamedPipe 函数来读取。
如果当 ReadFile 在管道上返回 TRUE 时,lpNumberOfBytesRead 参数为零,则管道的另一端调用 WriteFile 函数,并将 nNumberOfBytesToWrite 设置为零。
有关管道的详细信息,请参阅 管道。
事务处理操作
如果存在绑定到文件句柄的事务,则该函数将从文件的事务处理视图中返回数据。 事务处理读取句柄保证在句柄持续时间内显示文件的相同视图。 有关详细信息,请参阅 关于事务 NTFS。在 Windows 8 和 Windows Server 2012 中,此函数由以下技术支持。
技术 | 支持 |
---|---|
服务器消息块 (SMB) 3.0 协议 | 是 |
SMB 3.0 透明故障转移 (TFO) | 是 |
具有横向扩展文件共享的 SMB 3.0 (SO) | 是 |
群集共享卷文件系统 (CSV) | 是 |
弹性文件系统 (ReFS) | 是 |
示例
有关演示如何测试文件结尾的代码示例,请参阅 测试文件结尾。 有关其他示例,请参阅创建和使用临时文件和打开文件进行读取或写入。
要求
最低受支持的客户端 | Windows XP [桌面应用 | UWP 应用] |
最低受支持的服务器 | Windows Server 2003 [桌面应用 | UWP 应用] |
目标平台 | Windows |
标头 | fileapi.h (包括 Windows.h) |
Library | Kernel32.lib |
DLL | Kernel32.dll |