您的位置:首页 > 其它

异步读写文件

2012-09-28 16:54 351 查看
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <conio.h>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
enum class FileIo
{
	FI_NONE,
	FI_READ,
	FI_WRITE,
};

const int buffer_size = 10240000;
class MyOverlapped
{
public:
	OVERLAPPED	m_ol;
	FileIo		m_io;
	char		m_buffer[buffer_size];
	int			m_readPos;
	int			m_totalRead;
	int			m_writePos;
	int			m_totalWrite;
	int			m_fileSize;
	CRITICAL_SECTION	m_cs;
public:
	MyOverlapped() : m_io(FileIo::FI_NONE), m_readPos(0), m_totalRead(0),  m_writePos(0), m_totalWrite(0)
	{
	}
	void Init()
	{
		m_io = FileIo::FI_NONE;
		m_readPos = 0;
		m_totalRead = 0;
		m_writePos = 0;
		m_totalWrite = 0;

		::InitializeCriticalSection(&m_cs);
		ZeroMemory(&m_ol, sizeof(m_ol));
	}
	void fini()
	{
		DeleteCriticalSection(&m_cs);
	}
	~MyOverlapped()
	{
	}
};
struct FileHandle
{
	HANDLE hRead;
	HANDLE hWrite;
};
void CALLBACK workItem(PTP_CALLBACK_INSTANCE, PVOID pvContext, PTP_WORK ptWork)
{
	HANDLE hCompletionPort = (HANDLE)pvContext;
	DWORD dwTransferred;
	DWORD dwCompletionKey;
	LPOVERLAPPED pOverlapped = NULL;
	BOOL bStatus;
	MyOverlapped* pMyOverlapped = NULL;
	DWORD dwNumsRead, dwNumsWrite;
	while (true)
	{
		bStatus = GetQueuedCompletionStatus(hCompletionPort, &dwTransferred, &dwCompletionKey, &pOverlapped, INFINITE);
		if (bStatus)
		{
			if (dwTransferred == 0)//读取完毕
			{
				//要关闭
				cout << "finished\n";
				break;
			}
			pMyOverlapped = CONTAINING_RECORD(pOverlapped, MyOverlapped, m_ol);
			EnterCriticalSection(&(pMyOverlapped->m_cs));
			FileHandle* pHandle = (FileHandle*)dwCompletionKey; // 文件关联的句柄。
			if (pMyOverlapped->m_io == FileIo::FI_READ) // 读取完毕,要写。
			{
				//开始异步写
				HANDLE hWrite = pHandle->hWrite;
				pMyOverlapped->m_readPos += dwTransferred;
				pMyOverlapped->m_ol.Offset = pMyOverlapped->m_writePos; // 更新下一次读的位置。
				pMyOverlapped->m_totalRead += dwTransferred;
				pMyOverlapped->m_io = FileIo::FI_WRITE;
				cout << "读:" << dwTransferred << "字节,开始写……\n";
				WriteFile(hWrite, pMyOverlapped->m_buffer, dwTransferred, &dwNumsWrite, &(pMyOverlapped->m_ol));
			}
			else if (pMyOverlapped->m_io == FileIo::FI_WRITE)
			{
				HANDLE hRead = pHandle->hRead;
				pMyOverlapped->m_writePos += dwTransferred; // 更新写的位置
				pMyOverlapped->m_io = FileIo::FI_READ;
				pMyOverlapped->m_ol.Offset = pMyOverlapped->m_readPos;
				pMyOverlapped->m_totalWrite += dwTransferred;

				cout << "写:" << dwTransferred << "字节,开始读……\n" ;
				if (pMyOverlapped->m_totalWrite == pMyOverlapped->m_fileSize)
				{
					cout << "工作完成.\n";
					break;
				}
				ReadFile(hRead, pMyOverlapped->m_buffer, buffer_size, &dwNumsRead, &(pMyOverlapped->m_ol));
			}
			LeaveCriticalSection(&(pMyOverlapped->m_cs));
		}
					
	}
}
void WaitKeboard()
{
	while(!_kbhit());
}

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
	FileHandle fh;
	fh.hRead = CreateFile(L"D:\\netfox.rar", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
	fh.hWrite= CreateFile(L"D:\\cpy.rar", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
	//关联iocp端口
	CreateIoCompletionPort(fh.hRead, hIOCP, (DWORD)&fh, 0);
	CreateIoCompletionPort(fh.hWrite, hIOCP, (DWORD)&fh, 0);
	DWORD dwFileSize = GetFileSize(fh.hRead, NULL);
	MyOverlapped *myol = (MyOverlapped*)GlobalLock(GlobalAlloc(GPTR, sizeof(MyOverlapped)));
	myol->Init();

	myol->m_totalRead = dwFileSize;
	myol->m_fileSize = dwFileSize;
	PTP_WORK hWork = CreateThreadpoolWork(&workItem, PVOID(hIOCP), NULL);
	DWORD dwNumRead;

	SubmitThreadpoolWork(hWork);
	myol->m_io = FileIo::FI_READ;
	ReadFile(fh.hRead, myol->m_buffer, buffer_size, &dwNumRead, &(myol->m_ol));

	WaitKeboard();
	//PostQueuedCompletionStatus(hIOCP, 0, 0, NULL);
	myol->fini();
	GlobalFree(myol);
	CloseHandle(fh.hRead);
	CloseHandle(fh.hWrite);
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: