我是靠谱客的博主 大意爆米花,最近开发中收集的这篇文章主要介绍用IO完成端口实现文件异步读操作,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

IO完成端口是个比较复杂的内核对象,目前本人也是处于学习中,先写一个文件读写的例子,其中文件读用IO完成端口,文件写暂时用阻塞的方式,避免开始就难理解的局面。
下面直接上代码。

// FileOverlapped.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>


DWORD WINAPI ThreadFunc(LPVOID);


HANDLE hFileRead = INVALID_HANDLE_VALUE;
HANDLE hFileWrite = INVALID_HANDLE_VALUE;

#define LEN_READ_WRITE 1024
DWORD dwFileLen = 0;
DWORD dwFileAlreadyReadLen = 0;

typedef struct
{
	OVERLAPPED overlap;
	char buf[1024];
} cp_overlapped;

cp_overlapped *pCpOverLapped = NULL;

int main()
{
	hFileRead = CreateFile("D:\video\xingjichuanyue.rmvb", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL);
	if (hFileRead == INVALID_HANDLE_VALUE)
	{
		return -1;
	}

	hFileWrite = CreateFile("D:\video\xingjichuanyue_normal.rmvb", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFileWrite == INVALID_HANDLE_VALUE)
	{
		return -1;
	}
	dwFileLen = GetFileSize(hFileRead, NULL);

	pCpOverLapped = new cp_overlapped;
	pCpOverLapped->overlap.hEvent = NULL;
	pCpOverLapped->overlap.Offset = 0;
	pCpOverLapped->overlap.OffsetHigh = 0;

	HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
	HANDLE iocp2 = CreateIoCompletionPort(hFileRead, iocp, 10001, 0);
	BOOL bRet = ReadFile(hFileRead, pCpOverLapped->buf, LEN_READ_WRITE, NULL, &pCpOverLapped->overlap);
	DWORD err = ::GetLastError();

	HANDLE hThread;
	DWORD  threadId;
	hThread = CreateThread(NULL, 0, ThreadFunc, (LPVOID)iocp, 0, &threadId); // 创建线程

	WaitForSingleObject(hThread, INFINITE);
    return 0;
}


DWORD WINAPI ThreadFunc(LPVOID p)
{
	HANDLE iocp = (HANDLE)p;
	DWORD dwReaded = 0;
	DWORD key = 0;
	cp_overlapped * s = 0;
	while (1)
	{
		dwReaded = 0;
		BOOL bRet = GetQueuedCompletionStatus(iocp, &dwReaded, &key, (LPOVERLAPPED*)&s, INFINITE);
		if (bRet)
		{
			bRet = WriteFile(hFileWrite, s->buf, dwReaded, NULL, NULL);
			if (dwReaded <= 0)
			{
				CloseHandle(hFileWrite);
				break;
			}
			dwFileAlreadyReadLen += dwReaded;
			if (dwFileAlreadyReadLen >= dwFileLen)
			{
				CloseHandle(hFileWrite);
				break;
			}
			pCpOverLapped->overlap.hEvent = NULL;
			pCpOverLapped->overlap.Offset += dwReaded;
			pCpOverLapped->overlap.OffsetHigh = 0;  
			bRet = ReadFile(hFileRead, pCpOverLapped->buf, LEN_READ_WRITE, NULL, &pCpOverLapped->overlap);
		}
	}
	return 0;
}

代码里面,线程函数里面有这么两句话,pCpOverLapped->overlap.Offset += dwReaded;
pCpOverLapped->overlap.OffsetHigh = 0; 这个是文件偏移量,告知操作系统,文件从什么位置开始读,这个必须设置,如果不设置,则每次读取的都是最开始的1024个字节。还有就是如果文件读完了,发起ReadFile请求时,GetQueuedCompletionStatus会阻塞,所以判断文件是否读完,需要事先获取文件的大小,这点与同步读不一样,同步读不需要获取文件大小。

最后

以上就是大意爆米花为你收集整理的用IO完成端口实现文件异步读操作的全部内容,希望文章能够帮你解决用IO完成端口实现文件异步读操作所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部