当您打开带有FILE_FLAG_OVERLAPPED
标志的文件,然后使用带有 的OVERLAPPED
结构时ReadFile()
,使用OVERLAPPED.Offset
andOVERLAPPED.OffsetHigh
字段来指定应该从哪里开始读取的字节偏移量。此外,如果同时运行它们,则必须为它们使用单独的OVERLAPPED
实例。这在文档ReadFile()
中明确说明:
如果使用 FILE_FLAG_OVERLAPPED 打开 hFile,则 lpOverlapped 参数必须指向一个有效且唯一的OVERLAPPED 结构,否则该函数会错误地报告读取操作已完成。
对于支持字节偏移的 hFile,如果使用此参数,则必须指定开始从文件或设备读取的字节偏移。这个偏移量是通过设置 OVERLAPPED 结构的 Offset 和 OffsetHigh 成员来指定的。对于不支持字节偏移的 hFile,Offset 和 OffsetHigh 将被忽略。
由于您的行长度相同,您可以轻松计算第二行和第四行ReadFile()
的偏移量,然后针对这些偏移量发出两次异步调用,然后根据需要等待两个操作完成。
FILE_FLAG_NO_BUFFERING
附带说明一下,除非您真的知道自己在做什么,否则您真的不应该使用:
使用该标志成功处理使用 CreateFile 打开的文件有严格的要求FILE_FLAG_NO_BUFFERING
,有关详细信息,请参阅文件缓冲。
尝试更多类似的东西:
#include <vector>
BOOL ReadFromFileAsync(PCTSTR path)
{
BOOL bResult = FALSE;
HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED /*| FILE_FLAG_NO_BUFFERING*/, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
_tprintf_s(TEXT("Error opening file: %s\n"), path);
return FALSE;
}
DWORD dwLineSize = ...; // size of each line, in bytes
std::vector<BYTE> bSecondLineBuf(dwLineSize);
std::vector<BYTE> bFourthLineBuf(dwLineSize);
OVERLAPPED oReadSecondLine = { 0 };
OVERLAPPED oReadFourthLine = { 0 };
oReadSecondLine.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!oReadSecondLine.hEvent)
{
_tprintf_s(TEXT("Error creating I/O event for reading second line\n"));
goto done;
}
oReadSecondLine.Offset = ...; // offset of second line
oReadFourthLine.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!oReadFourthLine.hEvent)
{
_tprintf_s(TEXT("Error creating I/O event for reading fourth line\n"));
goto done;
}
oReadFourthLine.Offset = ...; // offset of fourth line
if (!ReadFile(hFile, &bSecondLineBuf[0], dwLineSize, NULL, &oReadSecondLine))
{
if (GetLastError() != ERROR_IO_PENDING)
{
_tprintf_s(TEXT("Error starting I/O to read second line\n"));
goto done;
}
}
if (!ReadFile(hFile, &bFourthLineBuf[0], dwLineSize, NULL, &oReadFourthLine))
{
if (GetLastError() != ERROR_IO_PENDING)
{
_tprintf_s(TEXT("Error starting I/O to read fourth line\n"));
CancelIo(hFile);
goto done;
}
}
// perform some stuff asynchronously
_tprintf_s(TEXT("HEY\n"));
HANDLE hEvents[2];
hEvents[0] = oReadSecondLine.hEvent;
hEvents[1] = oReadFourthLine.hEvent;
DWORD dwWaitRes = WaitForMultipleObjects(_countof(hEvents), hEvents, TRUE, INFINITE);
if (dwWaitRes == WAIT_FAILED)
{
_tprintf_s(TEXT("Error waiting for I/O to finish\n"));
CancelIo(hFile);
goto done;
}
_tprintf_s(TEXT("Strings that were read from file: "));
for (int i = 0; i < oReadSecondLine.InternalHigh; ++i)
_tprintf_s(TEXT("%c"), (TCHAR) &bSecondLineBuf[i]);
_tprintf_s(TEXT("\n"));
for (int i = 0; i < oReadFourthLine.InternalHigh; ++i)
_tprintf_s(TEXT("%c"), (TCHAR) &bFourthLineBuf[i]);
_tprintf_s(TEXT("\n"));
done:
if (oReadSecondLine.hEvent) CloseHandle(oReadSecondLine.hEvent);
if (oReadFourthLine.hEvent) CloseHandle(oReadFourthLine.hEvent);
CloseHandle(hFile);
return bResult;
}
或者:
#include <vector>
BOOL ReadFromFileAsync(PCTSTR path)
{
BOOL bResult = FALSE;
HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED /*| FILE_FLAG_NO_BUFFERING*/, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
_tprintf_s(TEXT("Error opening file: %s\n"), path);
return FALSE;
}
DWORD dwLineSize = ...; // size of each line, in bytes
std::vector<BYTE> bSecondLineBuf(dwLineSize);
std::vector<BYTE> bFourthLineBuf(dwLineSize);
OVERLAPPED oReadSecondLine = { 0 };
OVERLAPPED oReadFourthLine = { 0 };
oReadSecondLine.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!oReadSecondLine.hEvent)
{
_tprintf_s(TEXT("Error creating I/O event for reading second line\n"));
goto done;
}
oReadSecondLine.Offset = ...; // offset of second line
oReadFourthLine.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!oReadFourthLine.hEvent)
{
_tprintf_s(TEXT("Error creating I/O event for reading fourth line\n"));
goto done;
}
oReadFourthLine.Offset = ...; // offset of fourth line
if (!ReadFile(hFile, &bSecondLineBuf[0], dwLineSize, NULL, &oReadSecondLine))
{
if (GetLastError() != ERROR_IO_PENDING)
{
_tprintf_s(TEXT("Error starting I/O to read second line\n"));
goto done;
}
}
if (!ReadFile(hFile, &bFourthLineBuf[0], dwLineSize, NULL, &oReadFourthLine))
{
if (GetLastError() != ERROR_IO_PENDING)
{
_tprintf_s(TEXT("Error starting I/O to read fourth line\n"));
CancelIo(hFile);
goto done;
}
}
// perform some stuff asynchronously
_tprintf_s(TEXT("HEY\n"));
HANDLE hEvents[2];
hEvents[0] = oReadSecondLine.hEvent;
hEvents[1] = oReadFourthLine.hEvent;
OVERLAPPED* pOverlappeds[2];
pOverlappeds[0] = &oReadSecondLine;
pOverlappeds[1] = &oReadFourthLine;
BYTE* pBufs[2];
pBufs[0] = &bSecondLineBuf[0];
pBufs[1] = &bFourthLineBuf[0];
DWORD dwNumReads = _countof(hEvents);
do
{
DWORD dwWaitRes = WaitForMultipleObjects(dwNumReads, hEvents, FALSE, INFINITE);
if (dwWaitRes == WAIT_FAILED)
{
_tprintf_s(TEXT("Error waiting for I/O to finish\n"));
CancelIo(hFile);
goto done;
}
if ((dwWaitRes >= WAIT_OBJECT_0) && (dwWaitRes < (WAIT_OBJECT_0+dwNumReads)))
{
DWORD dwIndex = dwWaitRes - WAIT_OBJECT_0;
_tprintf_s(TEXT("String that was read from file: "));
for (int i = 0; i < pOverlappeds[dwIndex]->InternalHigh; ++i)
_tprintf_s(TEXT("%c"), (TCHAR) pBufs[dwIndex][i]);
_tprintf_s(TEXT("\n"));
--dwNumReads;
if (dwNumReads == 0)
break;
if (dwIndex == 0)
{
hEvents[0] = hEvents[1];
pOverlappeds[0] = pOverlappeds[1];
pBufs[0] = pBufs[1];
}
}
}
while (true);
done:
if (oReadSecondLine.hEvent) CloseHandle(oReadSecondLine.hEvent);
if (oReadFourthLine.hEvent) CloseHandle(oReadFourthLine.hEvent);
CloseHandle(hFile);
return bResult;
}