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 标志打开的任何句柄,也可以是 套接字 或 接受 函数返回的套接字句柄。
[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,如果使用此参数,则必须指定从文件或设备开始读取的字节偏移量。 通过设置 Offset 和 OffsetHighOVERLAPPED 结构的成员来指定此偏移量。 对于不支持字节偏移的 hFile,将忽略 Offset 和 OffsetHigh。
有关 lpOverlapped 和 FILE_FLAG_OVERLAPPED的不同组合的详细信息,请参阅“备注”部分和 同步和文件位置 部分。
返回值
如果函数成功,则返回值为非零(TRUE)。
如果函数失败或异步完成,则返回值为零(FALSE)。 若要获取扩展的错误信息,请调用 GetLastError 函数。
注意
GetLastError 代码 ERROR_IO_PENDING 不是失败;它指定读取操作正在异步等待完成。 有关详细信息,请参阅“备注”。
言论
发生以下情况之一时,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 参数必须指向有效的唯一 重叠 结构,否则该函数可能会错误地报告读取操作已完成。
- lpNumberOfBytesRead 参数应设置为 null 。 使用 GetOverlappedResult 函数获取读取的实际字节数。 如果 hFile 参数与 I/O 完成端口相关联,则还可以通过调用 GetQueuedCompletionStatus 函数来获取读取的字节数。
同步和文件位置
如果使用 FILE_FLAG_OVERLAPPED打开 hFile,则它是异步文件句柄;否则为同步。 如前所述,使用 OVERLAPPED 结构的规则略有不同。
注意
如果打开文件或设备进行异步 I/O,则后续调用函数(如 ReadFile)通常会立即返回,但也可以在阻止的执行方面同步运行。 有关详细信息,请参阅 异步磁盘 I/O 在 Windows上显示为同步。
使用异步文件句柄的注意事项:
- ReadFile 可能会在读取操作完成之前返回。 在此方案中,ReadFile 返回 FALSE,GetLastError 函数返回 ERROR_IO_PENDING,这允许调用进程在系统完成读取操作时继续。
-
lpOverlapped 参数不得 NULL,并且应用于以下事实:
- 尽管系统会自动设置和重置在 OVERLAPPED 结构中指定的事件,但 OVERLAPPED 结构中指定的偏移量不会自动更新。
- ReadFile 启动 I/O 操作时将事件重置为非对齐状态。
- OVERLAPPED 结构中指定的事件在读取操作完成时设置为信号状态;直到该时间,读取操作被视为挂起。
- 由于读取操作从在 OVERLAPPED 结构中指定的偏移量开始,并且 ReadFile 可能会在系统级读取操作完成(读取挂起)之前返回,因此应用程序不应修改、释放或重用结构的任何其他部分,直到发出事件信号(即, 读取完成)。
- 如果在异步操作期间检测到文件结束(EOF),则调用该操作 的 getOverlappedResult 返回 FALSE,GetLastError 返回 ERROR_HANDLE_EOF。
使用同步文件句柄的注意事项:
- 如果 lpOverlappedNULL,则读取操作从当前文件位置开始,ReadFile 在操作完成之前不会返回,并且系统在 ReadFile 返回之前更新文件指针。
- 如果 lpOverlapped 未 NULL,则读取操作从 OVERLAPPED 结构中指定的偏移量开始,ReadFile 在读取操作完成之前不会返回。 系统更新 重叠 偏移量和文件指针,然后 ReadFile 返回。
- 如果 lpOverlappedNULL,则在同步读取操作到达文件末尾时,ReadFile 返回 true true 并将
*lpNumberOfBytesRead
设置为零。 - 如果 lpOverlapped 未 NULL,则在同步读取操作到达文件的末尾时,ReadFile 返回 FALSE,GetLastError 返回 ERROR_HANDLE_EOF。
有关详细信息,请参阅 CreateFile 和 同步和异步 I/O。
管道
如果使用匿名管道并且写入句柄已关闭,则当 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) | 是的 |
群集共享卷文件系统 (CsvFS) | 是的 |
可复原文件系统 (ReFS) | 是的 |
例子
有关演示如何测试文件结束的代码示例,请参阅 测试文件结束。 有关其他示例,请参阅 创建和使用临时文件,打开文件以读取或写入。
要求
要求 | 价值 |
---|---|
最低支持的客户端 | Windows XP [桌面应用 |UWP 应用] |
支持的最低服务器 | Windows Server 2003 [桌面应用 |UWP 应用] |
目标平台 | 窗户 |
标头 | fileapi.h (包括 Windows.h) |
库 | Kernel32.lib |
DLL | Kernel32.dll |