ReadFile功能需要一个打开阅读或阅读和写入的文件句柄。ReadFile将指定数量的字节从当前位置复制到文件末尾到指定的缓冲区。当前位置是指定的OVERLAPPED结构的当前文件指针设置或抵消和OffsetHigh成员。该函数返回在其第四个参数指定的变量中读取的实际字节数。
WriteFile功能需要一个可用于写入或写入和读取的文件句柄。WriteFile将指定数量的字节从当前位置复制到缓冲区的末尾到指定的文件。该函数返回由第四个参数指定的变量中写入的实际字节数。
以下示例说明了使用回调完成异步I / O的可能流程。
完成例程:
VOID IoCompletionRoutine(DWORD dwErrorCode,
DWORD dwNumberOfBytesTransfer,LPOVERLAPPED lpOverlapped)
{
//如果发生I / O错误,显示错误并退出。
if(dwErrorCode){
printf(“FATAL I / O错误%ld I / O上下文%lx。%lx \\ n”,
dwErrorCode, lpOverlapped, lpOverlapped->hEvent);
ExitProcess(dwErrorCode);
}
LocalFree(lpOverlapped);
}
主线程:
VOID IoWorkerThread(VOID)
{
HANDLE HandleVector[2];
DWORD CompletionStatus;
PIOREQUEST IoRequestPacket;
LPOVERLAPPED Overlapped;
BOOL IoOperationStatus;
HandleVector[0] = IoWorkerListLock;
HandleVector[1] = IoWorkerListSemaphore;
for(;;) {
//在句柄向量上执行一个alertable等待。
两个对象
//同时发出信号意味着有一个
//队列中的I / O请求和调用者具有排他性
//访问队列。
CompletionStatus = WaitForMultipleObjectsEx(2, HandleVector,
TRUE, INFINITE, TRUE);
//如果等待失败,则出错。
if (CompletionStatus == 0xFFFFFFFF) {
printf("FATAL WAIT ERROR %ld\n", GetLastError());
ExitProcess(1);
}
//如果发生I / O完成,请等待另一个
// I / O请求或I / O完成。
if (CompletionStatus != WAIT_IO_COMPLETION) {
//等待满意I / O的所有权
//请求队列是排他的,还有一些东西
//队列。要插入队列中的东西,
//插入器获取列表锁(mutex),插入一个条目,
//表示列表信号量,最后释放
//列表锁
IoRequestPacket = RemoveHeadList(&IoRequestList);
ReleaseMutex(IoWorkerListLock);
//分配一个重叠的结构。
Overlapped = LocalAlloc(LMEM_ZEROINIT,
sizeof(OVERLAPPED));
if(!Overlapped){
printf("FATAL allocation error\n");
ExitProcess(1);
}
Overlapped->Offset = IoRequestPacket->Offset;
Overlapped->OffsetHigh = IoRequestPacket->OffsetHigh;
Overlapped->hEvent =
IoRequestPacket->dwAdditionalIoContext;
if(IoRequestPacket- > bRead){
IoOperationStatus =
ReadFileEx(IoRequestPacket->hFile,
IoRequestPacket->lpBuffer,
IoRequestPacket->dwTransferCount,
Overlapped, IoCompletionRoutine);
}
else {
IoOperationStatus =
WriteFileEx(IoRequestPacket->hFile,
IoRequestPacket->lpBuffer,
IoRequestPacket->dwTransferCount,
重叠,
IoCompletionRoutine);
}
//测试以查看I / O是否成功排队。
if(!IoOperationStatus){
printf(“FATAL I / O错误%ld I / O上下文%lx。%lx \\ n”,
GetLastError(), Overlapped, Overlapped->hEvent);
ExitProcess(1);
}
// I / O队列成功。回到
// alertable等待I / O完成或
//更多的I / O请求。
}
}
}
SetFilePointer函数将文件指针相对于文件的开头或结尾或文件指针的当前位置移动指定的字节数。如果指定了正的字节数,SetFilePointer将文件指针移动到文件的末尾;负值将指针移动到文件的开头。
以下示例将一个文件附加到另一个文件的末尾。该应用程序使用CreateFile打开两个文件:ONE.TXT打开以供阅读,TWO.TXT打开以进行写入。然后应用程序通过使用ReadFile和WriteFile读写4K块,将ONE.TXT的内容追加到TWO.TXT的末尾。在写入第二个文件之前,应用程序使用SetFilePointer将第二个文件的指针设置到文件的末尾,并使用LockFile锁定要写入的区域。这样可以防止在写入过程中另一个进程访问该区域。每次写操作后,UnlockFile解锁锁定区域。
HANDLE hFile;
HANDLE hAppend;
DWORD dwBytesRead, dwBytesWritten, dwPos;
char buff[4096];
//打开现有文件。
hFile = CreateFile("ONE.TXT", //打开ONE.TXT
GENERIC_READ, //打开阅读
0, //不要分享
NULL, //没有安全
OPEN_EXISTING, //仅存在文件
FILE_ATTRIBUTE_NORMAL, //普通文件
NULL); //没有attr。模板
if (hFile == INVALID_HANDLE_VALUE) {
ErrorHandler("Could not open ONE."); //进程错误
}
//打开现有文件,或者文件不存在,
//创建一个新的文件。
hAppend = CreateFile("TWO.TXT", //打开TWO.TXT
GENERIC_WRITE, //打开写作
0, //不要分享
NULL, //没有安全
OPEN_ALWAYS, //打开或创建
FILE_ATTRIBUTE_NORMAL, //普通文件
NULL); //没有attr。模板
if (hAppend == INVALID_HANDLE_VALUE) {
ErrorHandler("Could not open TWO."); //进程错误
}
//将第一个文件附加到第二个文件的末尾。
//锁定第二个文件以防止其他进程
//写入时访问它。解锁
//文件写入完成后
do {
if(ReadFile(hFile,buff,4096,& dwBytesRead,NULL)){
dwPos = SetFilePointer(hAppend, 0, NULL, FILE_END);
LockFile(hAppend, dwPos, 0, dwPos + dwBytesRead, 0);
WriteFile(hAppend,buff,dwBytesRead,
&dwBytesWritten, NULL);
UnlockFile(hAppend, dwPos, 0, dwPos + dwBytesRead, 0);
}
} while (dwBytesRead == 4096);
//关闭这两个文件。
CloseHandle(hFile);
CloseHandle(hAppend);