要想使用异步的ReadFile或者WriteFile,就要有这个Overlapped I/O。
Overlapped I/O的作用就是当处理大量的读取和写入操作时,不会导致堵塞。因为不用这个Overlapped I/O的话,会导致线程堵塞。
大概需要3步
1、使用CreateFile()创建文件或者打开文件
HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDispostion ,
DWORD dwFlagsAndAttributes,//这里设置为FILE_FLAG_OVERLAPPED
HANDLE hTemplateFile);
2、使用ReadFile或者WriteFile。
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped); //传入OVERLAPPED变量
3、使用GetOverlappedResult或者 WaitForSingObject进行等待
例子如下:
#include <iostream>
#include <windows.h>
using namespace std;
/*
首先使用 OVERLAPPED 结构, 其中有Event 对象, 可用可不用,这个例子先不用
CreateFile 其中一个参数使用 FILE_FLAG_OVERLAPPED
ReadFile 默认同步, 在最后一个参数使用 OVERLAPPED ;
ReadFile 返回TRUE ,则代表已经读完了
否则应该检查 GetLastError , 系统是否为此安排了等待.
如果 GetLastError == ERROR_IO_PENDING ,则成功了, 等着取数据, 否则失败
之后可以使用 GetOverlappedResult(最后一个参数为TRUE) / WaitForSingObject 来等待直到完成;
*/
void read_overlapped(const TCHAR * path)
{
//这里没有使用其中的 Event 对象.
OVERLAPPED overlap = { 0 };
DWORD bytesReaded = 0;
BOOL ret = FALSE;
char * buf = new char[8196 * 10];
// 注意:FILE_FLAG_OVERLAPPED
HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (INVALID_HANDLE_VALUE == hFile){
cout << "INVALID_HANDLE_VALUE" << endl;
return;
}
//从哪开始读文件
overlap.Offset = 0;
//注意overlap 需要传入
ret = ReadFile(hFile, buf, 8196 * 10, &bytesReaded
, &overlap);
//直接就完成了, 您的计算机硬盘可真快
if (ret){
cout << "done :" << bytesReaded << endl;
cout << buf << endl;
}
else
{
//检测一下错误, 确认是否已经进入准备状态
DWORD err = GetLastError();
//ok
if (ERROR_IO_PENDING == err)
{
//GetOverlappedResult(hFile,&overlap,&bytesReaded,TRUE); 相当于WaitForSingObject
cout << "LOADing: " << GetLastError() << endl;
ret = GetOverlappedResult(hFile, &overlap, &bytesReaded, TRUE);
if (ret){
cout << "ret:" << ret << ",bytesread:" << bytesReaded << endl;
}
}
else
{
cout << "err : " << err << endl;
}
}
CloseHandle(hFile);
}
//多同一个文件多次读取
void read_overlapped2(const TCHAR * path)
{
HANDLE event_handles[2];
OVERLAPPED overlap[2] = { 0 };
char * buf[2] = { 0 };
DWORD num = 0;
HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (INVALID_HANDLE_VALUE == hFile){
cout << "INVALID_HANDLE_VALUE" << endl;
return;
}
BOOL ret = 0;
int success_len = 0;
for (int i = 0; i < 2; ++i){
event_handles[i] = CreateEvent(0, TRUE, FALSE, NULL);
overlap[i].hEvent = event_handles[i];
overlap[i].Offset = i * 1000 + i;
buf[i] = new char[8196 * 1024];
ret = ReadFile(hFile, buf[i], 8196 + overlap[i].Offset, &num, &overlap[i]);
if (ret){
cout << "index:" << i << ", is done" << endl;
cout << "index:" << i << ",num:" << num;
cout << "index:" << i << buf[i] << endl;
++success_len;
}
else {
if (GetLastError() != ERROR_IO_PENDING){
cout << "index:" << i << "failed" << endl;
delete[] buf[i];
SetEvent(event_handles[i]);
}
else {
++success_len;
}
}
}
cout << "success_len:" << success_len << endl;
//WaitForMultipleObjects(success_len, event_handles, TRUE, INFINITE);这个要不要无所谓的,因为GetOverlappedResult函数具有等待功能
ret = GetOverlappedResult(hFile, &overlap[0], &num, FALSE);
cout << "ret:" << ret << ", num:" << num << endl;
ret = GetOverlappedResult(hFile, &overlap[1], &num, FALSE);
cout << "ret:" << ret << ", num:" << num << endl;
CloseHandle(hFile);
}
int main()
{
//read_overlapped(L"1.txt");
read_overlapped2(L"1.txt");
system("pause");
return 0;
}