ReadFile函数从文件指针所指定的位置开始读取数据。读取操作完成后,文件指针将按实际读取的字节数进行调整,除非使用overlap属性创建文件句柄。如果为重叠的输入和输出(I / O)创建文件句柄,则应用程序必须在读取操作后调整文件指针的位置。
BOOL ReadFile(
HANDLE 【HFILE】, | //要处理的文件 |
LPVOID 【lpBuffer】, | //接收数据的缓冲区的地址 |
DWORD 【nNumberOfBytesToRead】, | //要读取的字节数 |
LPDWORD 【lpNumberOfBytesRead】, | //读取的字节数的地址 |
LPOVERLAPPED 【lpOverlapped的】 | //数据结构的地址 |
); |
参数
【HFILE】
标识要读取的文件。必须使用GENERIC_READ访问该文件创建文件句柄。
Windows NT
对于异步读取操作,【HFILE】可以是使用CreateFile函数的FILE_FLAG_OVERLAPPED标志打开的任何句柄,或插座或接受函数返回的套接字句柄。
Windows 95
对于异步读取操作,【HFILE】可以是通过CreateFile FILE_FLAG_OVERLAPPED标志打开的通信资源,邮槽或命名管道句柄,或插座或接受函数返回的套接字句柄。Windows 95不支持磁盘文件上的异步读取操作。
【lpBuffer】
指向从文件读取的数据的缓冲区。
【nNumberOfBytesToRead】
指定要从文件读取的字节数。
【lpNumberOfBytesRead】
指向读取的字节数。ReadFile在进行任何工作或错误检查之前将此值设置为零。如果ReadFile在命名管道上返回TRUE时,此参数为零,则消息模式管道的另一端称为WriteFile函数,【nNumberOfBytesToWrite】设置为零。
如果【lpOverlapped的】为NULL,则【lpNumberOfBytesRead】不能为NULL。
如果【lpOverlapped的】不为NULL,则【lpNumberOfBytesRead】可以为NULL。如果这是一个重叠的读操作,可以通过调用GetOverlappedResult获取读取的字节数。如果【HFILE】与I / O完成端口相关联,则可以通过调用GetQueuedCompletionStatus获取读取的字节数。
【lpOverlapped的】
指向OVERLAPPED结构。如果【HFILE】是使用FILE_FLAG_OVERLAPPED创建的,则此结构是必需的。
如果使用FILE_FLAG_OVERLAPPED打开【HFILE】,则【lpOverlapped的】参数不能为NULL。它必须指向一个有效的OVERLAPPED结构。如果【HFILE】使用FILE_FLAG_OVERLAPPED创建,并且【lpOverlapped的】为NULL,则该函数可能会错误地报告读操作完成。
如果使用FILE_FLAG_OVERLAPPED打开【HFILE】,并且【lpOverlapped的】不为NULL,则读操作从OVERLAPPED结构中指定的偏移开始,并且ReadFile可能在读操作完成之前返回。在这种情况下,ReadFile返回FALSE,GetLastError函数返回ERROR_IO_PENDING。这允许调用进程在读取操作完成时继续。OVERLAPPED结构中指定的事件在读取操作完成后设置为信号状态。
如果没有使用FILE_FLAG_OVERLAPPED打开【HFILE】,并且【lpOverlapped的】为NULL,则读取操作从当前文件位置开始,并且ReadFile不会返回,直到操作完成。
如果【HFILE】未使用FILE_FLAG_OVERLAPPED打开,并且【lpOverlapped的】不为NULL,则读操作从OVERLAPPED结构中指定的偏移开始。ReadFile直到读操作完成才返回。
返回值
如果函数成功,返回值不为零。
如果返回值为非零,读取的字节数为零,则在读取操作时,文件指针超出了文件的当前结尾。但是,如果使用FILE_FLAG_OVERLAPPED打开文件,并且【lpOverlapped的】不为NULL,则返回值为FALSE,并且当文件指针超出文件的当前结尾时,GetLastError返回ERROR_HANDLE_EOF。
如果函数失败,返回值为零。要获取扩展错误信息,请调用GetLastError.
备注
ReadFile返回以下其中一个为真:写入操作在管道的写入端完成,请求的字节数已被读取或发生错误。
如果文件的一部分被其他进程锁定,并且读取操作与锁定部分重叠,则此函数失败。
在读取操作完成之前,应用程序不得从读取操作正在读取或写入输入缓冲区。对输入缓冲区的过早访问可能导致读入该缓冲区的数据损坏。
可以通过使用带控制台输入句柄的ReadFile从控制台输入缓冲区中读取字符。控制台模式确定ReadFile功能的确切行为。
如果命名管道正在以消息模式读取,并且下一条消息长于【nNumberOfBytesToRead】参数指定,则ReadFile返回FALSE,GetLastError返回ERROR_MORE_DATA。消息的其余部分可以通过后续调用ReadFile或PeekNamedPipe函数来读取。
从通信设备读取时,ReadFile的行为由当前通信超时控制,使用SetCommTimeouts和GetCommTimeouts功能设置和检索。如果您无法设置超时值,则可能会发生不可预测的结果。有关通信超时的详细信息,请参阅COMMTIMEOUTS.
如果ReadFile尝试从缓冲区太小的邮槽读取,则函数返回FALSE,GetLastError返回ERROR_INSUFFICIENT_BUFFER。
如果匿名写管理句柄已关闭,并且ReadFile尝试使用相应的匿名读取管道句柄进行读取,则函数返回FALSE,GetLastError返回ERROR_BROKEN_PIPE。
当异常I / O请求过多时,ReadFile功能可能会失败,并返回ERROR_INVALID_USER_BUFFER或ERROR_NOT_ENOUGH_MEMORY。
用于检查文件结束条件(eof)的ReadFile代码因同步和异步读取操作而异。
当同步读取操作到达文件末尾时,ReadFile返回TRUE,并将* 【lpNumberOfBytesRead】设置为零。以下示例代码测试用于同步读取操作的文件结尾:
//尝试同步读操作
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead, NULL) ;
//检查eof
if (bResult && nBytesRead == 0, ) {
//我们在档案的最后
}
在ReadFile的初始化调用期间或在后续异步操作期间,异步读取操作可能会遇到文件的结尾。
如果异步读操作的ReadFile时间检测到EOF,则ReadFile返回FALSE,GetLastError返回ERROR_HANDLE_EOF。
如果在后续异步操作期间检测到EOF,则调用GetOverlappedResult以获得该操作的结果返回FALSE,GetLastError返回ERROR_HANDLE_EOF。
要取消所有挂起的异步I / O操作,请使用CancelIO功能。此函数仅取消调用线程为指定的文件句柄发出的操作。取消的I / O操作完成,错误ERROR_OPERATION_ABORTED。
以下示例代码说明了异步读取操作的文件结尾的测试:
//设置重叠的结构字段
//为了简化此示例,我们将避开一个事件句柄
gOverLapped.Offset = 0;
gOverLapped.OffsetHigh = 0;
gOverLapped.hEvent = NULL;
//尝试异步读取操作
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead,
&gOverlapped) ;
//如果有问题或异步。手术仍在等待...
如果(!bResult)
{
//处理错误代码
switch (dwError = GetLastError())
{
case ERROR_HANDLE_EOF:
{
//我们到达文件的末尾
//在调用ReadFile时
//代码来处理
}
case ERROR_IO_PENDING:
{
//异步i / o仍在进行中
//做一些其他事情一段时间
GoDoSomethingElse() ;
//检查异步读取的结果
bResult = GetOverlappedResult(hFile, &gOverlapped,
&nBytesRead, FALSE) ;
//如果有问题...
如果(!bResult)
{
//处理错误代码
switch (dwError = GetLastError())
{
case ERROR_HANDLE_EOF:
{
//我们到达文件的末尾
//异步操作
}
//处理其他错误的情况
}
}
} //最终情况
//处理其他错误的情况
} //结束开关
} // 万一
也可以看看
CancelIo, CreateFile, GetCommTimeouts, GetOverlappedResult, GetQueuedCompletionStatus, OVERLAPPED, PeekNamedPipe, ReadFileEx, SetCommTimeouts, WriteFile