深入解析Windows API中的ReadFile函数
创作时间:
作者:
@小白创作中心
深入解析Windows API中的ReadFile函数
引用
CSDN
等
7
来源
1.
https://blog.csdn.net/weixin_34405557/article/details/85563077
2.
https://www.easefilter.com/kb/fileapi-readfile.htm
3.
https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile#parameters
4.
https://learn.microsoft.com/zh-cn/windows/win32/fileio/testing-for-the-end-of-a-file
5.
https://learn.microsoft.com/zh-tw/windows/win32/api/fileapi/nf-fileapi-readfile
6.
https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile
7.
https://www.cnblogs.com/liujx2019/p/11691495.html
在Windows操作系统中,ReadFile函数是API的重要组成部分,用于从文件或设备(如串口、硬盘)中读取数据。它是同步和异步I/O操作的基础,广泛应用于文件读取、串口通信、网络通信以及传感器数据读取等多种场景。本文将深入解析ReadFile函数的参数、返回值及其实际应用示例,帮助开发者更好地理解和使用这一关键功能。
01
函数基础介绍
ReadFile函数是Windows API中用于读取文件或I/O设备数据的核心函数。其主要功能是从指定的文件或设备中读取数据到应用程序的缓冲区中。该函数支持同步和异步操作模式,适用于各种I/O设备,包括文件、串口、网络套接字等。
与其他读取函数(如fread、ReadFileEx)相比,ReadFile具有以下特点:
- 通用性:支持多种I/O设备,不仅限于文件
- 灵活性:同时支持同步和异步操作
- 系统级:直接与操作系统内核交互,性能更优
02
函数原型与参数详解
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
参数名称 | 类型 | 描述 |
|---|---|---|
hFile | HANDLE | 要读取的设备句柄(如文件、串口等) |
lpBuffer | LPVOID | 存储读取数据的缓冲区指针 |
nNumberOfBytesToRead | DWORD | 请求读取的最大字节数 |
lpNumberOfBytesRead | LPDWORD | 指向变量的指针,接收实际读取的字节数 |
lpOverlapped | LPOVERLAPPED | 异步操作时需提供的OVERLAPPED结构体指针 |
- hFile:要读取的设备句柄,必须具有读取权限。对于异步操作,句柄需要通过
CreateFile函数使用FILE_FLAG_OVERLAPPED标志创建,或者是一个由socket或accept函数返回的套接字句柄。 - lpBuffer:指向缓冲区的指针,用于存储读取的数据。在读取操作完成前,不应使用此缓冲区。
- nNumberOfBytesToRead:请求读取的最大字节数。
- lpNumberOfBytesRead:指向一个变量的指针,用于接收实际读取的字节数。在同步模式下必须提供,异步模式下可以为NULL。
- lpOverlapped:指向
OVERLAPPED结构体的指针。如果hFile是使用FILE_FLAG_OVERLAPPED打开的,则必须提供有效的OVERLAPPED结构体,否则可以为NULL。
03
返回值与错误处理
ReadFile函数的返回值是一个布尔值:
- 成功时返回非零值(
TRUE) - 失败时返回零(
FALSE)
当函数返回FALSE时,可以通过GetLastError()函数获取具体的错误码。常见的错误码包括:
ERROR_IO_PENDING:异步操作尚未完成ERROR_HANDLE_EOF:同步读取到达文件末尾ERROR_INVALID_HANDLE:无效的设备句柄ERROR_ACCESS_DENIED:没有读取权限
特别需要注意的是,ERROR_IO_PENDING并不表示错误,而是表明异步操作正在等待完成。在这种情况下,可以通过GetOverlappedResult函数检查操作的最终状态。
04
使用示例
同步读取示例
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE hFile = CreateFile("example.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("Failed to open file.\n");
return -1;
}
char buffer[1024];
DWORD bytesRead;
while (ReadFile(hFile, buffer, sizeof(buffer), &bytesRead, NULL)) {
if (bytesRead > 0) {
// 处理读取的数据
printf("%.*s", (int)bytesRead, buffer);
} else {
break; // 文件结束
}
}
DWORD error = GetLastError();
if (error != ERROR_SUCCESS && error != ERROR_HANDLE_EOF) {
printf("Error reading file: %lu\n", error);
}
CloseHandle(hFile);
return 0;
}
异步读取示例
#include <windows.h>
#include <stdio.h>
void GoDoSomethingElse() {
printf("Inside GoDoSomethingElse()\n");
}
DWORD AsyncReadFile(HANDLE hEvent, HANDLE hFile) {
char inBuffer[64];
DWORD nBytesToRead = 64;
DWORD dwBytesRead = 0;
OVERLAPPED stOverlapped = {0};
DWORD dwError = 0;
BOOL bResult = FALSE;
BOOL bContinue = TRUE;
stOverlapped.hEvent = hEvent;
while (bContinue) {
bResult = ReadFile(hFile, inBuffer, nBytesToRead, &dwBytesRead, &stOverlapped);
dwError = GetLastError();
if (!bResult) {
switch (dwError) {
case ERROR_HANDLE_EOF:
printf("\nReadFile returned FALSE and EOF condition, async EOF not triggered.\n");
break;
case ERROR_IO_PENDING:
while (TRUE) {
GoDoSomethingElse();
bResult = GetOverlappedResult(hFile, &stOverlapped, &dwBytesRead, FALSE);
if (!bResult) {
dwError = GetLastError();
if (dwError == ERROR_HANDLE_EOF) {
printf("GetOverlappedResult found EOF\n");
break;
} else if (dwError == ERROR_IO_INCOMPLETE) {
continue;
} else {
printf("Error in GetOverlappedResult: %lu\n", dwError);
break;
}
} else {
// 处理读取的数据
printf("%.*s", (int)dwBytesRead, inBuffer);
break;
}
}
break;
default:
printf("Error in ReadFile: %lu\n", dwError);
break;
}
} else {
// 处理读取的数据
printf("%.*s", (int)dwBytesRead, inBuffer);
}
}
return dwBytesRead;
}
05
注意事项
- 缓冲区管理:确保提供的缓冲区在读取操作完成前保持有效,不要在读取过程中释放或重用缓冲区。
- 异步操作的线程安全:在多线程环境中使用异步读取时,需要确保
OVERLAPPED结构体的线程安全性。 - 错误处理:始终检查
ReadFile的返回值,并在失败时调用GetLastError()获取详细错误信息。 - 文件末尾处理:在同步读取中,当
lpNumberOfBytesRead为0且GetLastError()返回ERROR_HANDLE_EOF时,表示已到达文件末尾。
06
对比分析
与ReadFileEx相比,ReadFile的主要区别在于:
ReadFile同时支持同步和异步操作,而ReadFileEx仅支持异步操作。ReadFile的异步操作需要手动检查完成状态,而ReadFileEx可以指定一个完成例程,在操作完成后自动调用。
总结来说,ReadFile函数是Windows API中处理文件和设备读取的核心工具。通过理解其参数、返回值和使用场景,开发者可以更有效地进行I/O操作,特别是在需要高性能和灵活控制的系统级开发中。
热门推荐
《自然·通讯》:科学家发现调控戒断反应的关键通道蛋白
舞蹈老师就业和发展前景
《浪漫爱情心理学》:爱情的核心本质是心理可见性
孩子不吃饭,“强行喂”还是“饿一顿”?有经验的家长都是这样做的...
护肝补剂选购避坑指南:水飞蓟素和姜黄素怎么选?
薄荷对猫有什么作用,有危害么(了解猫咪食物安全问题)
OODA与PDCA:哪个更适合你的组织?
真的有狗熊岭!中国东北部原始森林里的生态秘境
我可以使用哪些合法的渠道来确认某人的婚姻状态
一生必去的30个《国家地理》推荐美景,治愈你
光伏领域尺寸详解:电池片与组件规格大盘点
AI如何助力工业软件发挥作用?
人不会无缘无故得肝病?医生:患肝病的人,或是因为这 4个因素
荔枝肉的制作方法详解
卧室门选购,这5种果断拒绝,不是挑刺,是真的很影响居住体验
看懂后自己也能精准算分!一文明晰A-Level等级与三大考试局拼分和合分规则!
AI写作助手使用指南:六步优化你的首次提问
唐诗宋词里寓意好的女孩名字
卫青有一条“厚黑学”,学会后“领导不疑、同事不嫉、下属服气”
梦见现实生活中的人:心理学与传统文化的双重解读
孙兴慜零度角破门,热刺4-3晋级,曼联输球输人,止步英联杯八强
肾炎尿检的三个关键指标
肺癌晚期脑转移的症状及应对方法
前端如何自适应字体大小
茅山的主要景点介绍 中华道教名山
9天见了27位投资人,上海AI产业抢抓DeepSeek机遇上演竞速赛
残疾人税收优惠政策全解析
提肛运动:随时随地都能做的健康运动,5大好处助力肛肠健康
保护隐私,确保安全:利用生物特征认证API实现高级身份验证
从草根到总统,戎马一生,活到最后沦为乌克兰的罪人-亚努科维奇