ReadFile
基本概念
ReadFile
是Windows API
(Win32 API) 中的核心文件I/O
函数,用于从已打开的文件、设备(如串口、管道、磁盘分区)或I/O
对象中读取数据,是Windows
系统下底层数据读取的基础接口。它支持 同步读取
和异步读取
两种模式,适用于几乎所有Windows
可访问的I/O
设备。
ReadFile
的返回值为BOOL
类型,仅表示 函数调用是否成功启动/完成,不直接代表 “是否读取到数据”:
返回 TRUE
:
同步模式:读取操作已完成(可能读取到0字节,如文件末尾);
异步模式:读取操作已成功提交(需后续通过WaitForSingleObject
、GetOverlappedResult
等确认完成)。
返回FALSE
:
操作失败,需通过GetLastError()
函数获取具体错误码,常见错误包括:
ERROR_HANDLE_EOF
:已到达文件末尾(EOF),无更多数据可读;
ERROR_ACCESS_DENIED
:文件句柄无读权限;
ERROR_IO_PENDING
:异步操作尚未完成(非 “错误”,需等待);
ERROR_INVALID_HANDLE
:传入的hFile
是无效句柄。
语法
1 2 3 4 5 6 7
| BOOL ReadFile( [in] HANDLE hFile, [out] LPVOID lpBuffer, [in] DWORD nNumberOfBytesToRead, [out, optional] LPDWORD lpNumberOfBytesRead, [in, out, optional] LPOVERLAPPED lpOverlapped );
|
LPVOID定义:
1 2 3 4
| typedef void far *LPVOID;
void far * :表示 “可指向任意段内存的通用指针”; 总结:可指向任意类型数据的远指针.
|
LPDWORD定义:
1 2 3 4
| typedef DWORD far *LPDWORD;
DWORD :32 位无符号整数(等价于 unsigned long); 总结:指向 DWORD 类型的(远)指针.
|
LPOVERLAPPED定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| typedef struct _OVERLAPPED { ULONG_PTR Internal; ULONG_PTR InternalHigh; union { struct { DWORD Offset; DWORD OffsetHigh; } DUMMYSTRUCTNAME; PVOID Pointer; } DUMMYUNIONNAME;
HANDLE hEvent; } OVERLAPPED, *LPOVERLAPPED;
ULONG_PTR Internal :系统内部使用的字段,通常存储异步操作的状态信息(如错误码); ULONG_PTR InternalHigh :同样为系统内部使用,通常存储异步操作的结果(如实际传输的字节数); 联合体 DUMMYUNIONNAME : 子结构体 DUMMYSTRUCTNAME :包含 Offset(低 32 位)和 OffsetHigh(高 32 位)两个 DWORD 成员,合起来表示 64 位的文件偏移量, 用于文件 / 设备的异步读写操作,指定从文件的哪个位置开始读写(适用于支持随机访问的设备,如文件); PVOID Pointer :一个通用指针(void*),用于传递用户自定义的上下文数据; HANDLE hEvent :一个事件句柄(HANDLE),用于异步操作完成时的通知。 总结:OVERLAPPED 结构体是 Windows 重叠 I/O 模型的基础,用于在调用异步 API(如 ReadFileEx、WriteFileEx、WSARecv 等)时传递必要的上下文信息; LPOVERLAPPED是指向该结构体的指针类型。
|
简单示例(同步读取)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <windows.h> #include <stdio.h>
int main() { HANDLE hFile = CreateFile( L"test.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile == INVALID_HANDLE_VALUE) { printf("CreateFile failed! Error: %lu\n", GetLastError()); return 1; }
char buffer[1024] = {0}; DWORD bytesToRead = 1024; DWORD bytesRead = 0;
BOOL success = ReadFile( hFile, buffer, bytesToRead, &bytesRead, NULL );
if (success) { if (bytesRead == 0) { printf("已到达文件末尾(EOF)\n"); } else { printf("读取成功!实际读取 %lu 字节,内容:\n%s\n", bytesRead, buffer); } } else { printf("ReadFile failed! Error: %lu\n", GetLastError()); }
CloseHandle(hFile); return 0; }
|
WriteFile
基本概念
WriteFile
是Windows API
(Win32 API)用于向文件或其他可写设备(如管道、串口、磁盘等)写入数据的核心函数,支持同步和异步(重叠I/O
)两种操作模式。它是文件I/O
操作的基础API
之一,它是ReadFile
的对应函数,共同构成了文件I/O
的基础。
ReadFile
的返回值为BOOL
类型,
成功时返回 TRUE
(非零)。
失败时返回 FALSE(0)
,可通过GetLastError
获取具体错误码(如ERROR_ACCESS_DENIED
表示无权限,ERROR_DISK_FULL
表示磁盘满)。
特殊情况:异步操作时,若函数返回FALSE
且GetLastError
返回ERROR_IO_PENDING
,表示操作已成功发起并在后台进行,并非真正失败。
语法
1 2 3 4 5 6 7
| BOOL WriteFile( [in] HANDLE hFile, [in] LPCVOID lpBuffer, [in] DWORD nNumberOfBytesToWrite, [out, optional] LPDWORD lpNumberOfBytesWritten, [in, out, optional] LPOVERLAPPED lpOverlapped );
|
参数的数据类型和ReadFie
一样。
简单示例(同步写入)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <windows.h> #include <stdio.h>
int main() { HANDLE hFile = CreateFileA( "test.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile == INVALID_HANDLE_VALUE) { printf("打开文件失败,错误码: %d\n", GetLastError()); return 1; }
const char* data = "Hello, WriteFile!"; DWORD bytesToWrite = strlen(data); DWORD bytesWritten;
BOOL success = WriteFile( hFile, data, bytesToWrite, &bytesWritten, NULL );
if (success) { printf("写入成功,实际写入 %d 字节\n", bytesWritten); } else { printf("写入失败,错误码: %d\n", GetLastError()); }
CloseHandle(hFile); return 0; }
|