示例中分别使用了重叠结构与非重叠结构操作文件,你可以根据实际中的需求自己取舍。示例中有对API的简单注释,代码方便大家学习,共同进步。
如有不足,留言反馈
#include <windows.h>
int MAX_READ = (1024 * 1024);
/************************一般的读写文件操作************************/
void NomalReadWrite(TCHAR* pReadFile, TCHAR* pWriteFile)
{
// 读句柄
HANDLE hReadFile = CreateFile(
pReadFile, // 指向文件名的指针
GENERIC_READ, // 访问模式(写 / 读) GENERIC_ALL(读写)
FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享模式 (读,写)
0, // 指向安全属性的指针
OPEN_EXISTING, // 如何创建
FILE_ATTRIBUTE_NORMAL, // 文件属性
0); // 用于复制文件句柄
// 写句柄
HANDLE hWriteFile = CreateFile(pWriteFile,
GENERIC_WRITE,
FILE_SHARE_WRITE,
0,
OPEN_ALWAYS, // Opens a file, always.
FILE_ATTRIBUTE_NORMAL,
0);
if (hReadFile == INVALID_HANDLE_VALUE || hWriteFile == INVALID_HANDLE_VALUE)
return;
BYTE * buf = new BYTE[MAX_READ];
DWORD nBytesRead = -1;
DWORD nBytesWrite = 0;
while (nBytesRead != 0)// 文件读取完毕时,nBytesRead为0
{
if (!ReadFile(hReadFile, buf, MAX_READ, &nBytesRead, NULL))
break;
if (!WriteFile(hWriteFile, buf, nBytesRead, &nBytesWrite, NULL))
break;
}
CloseHandle(hReadFile);
CloseHandle(hWriteFile);
delete[] buf;
}
struct stBufInfo
{
BYTE** arrBuf; //异步读取的数据
DWORD* arrBytesRead; //读取的字节数
};
/********************重叠模式的读写文件操作(多次IO操作读取)*********************/
void MoreOverlapdReadWrite(TCHAR* pReadFile, TCHAR* pWriteFile)
{
HANDLE hReadFile = CreateFile(pReadFile,
GENERIC_READ, // 读文件模式
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,// 使用重叠IO模式读取文件
0);
if (hReadFile == INVALID_HANDLE_VALUE)
return;
DWORD dwSize = GetFileSize(hReadFile, NULL);
if (dwSize > MAX_READ * 63) // WaitForMultipleObjects一次最多只能等待64个事件对象,所以我们必须保证n的大小<=64
MAX_READ = dwSize / 63;
const int n = dwSize / MAX_READ + 1;
stBufInfo bufInfo = { 0 };
bufInfo.arrBuf = new BYTE*[n];
bufInfo.arrBytesRead = new DWORD[n];
LPOVERLAPPED ovlp = new OVERLAPPED[n];
HANDLE* arrEvt = new HANDLE[n];
BOOL bRet;
for (int i = 0; i < n; i++)
{
bufInfo.arrBuf[i] = new BYTE[MAX_READ];
ZeroMemory(&ovlp[i], sizeof(OVERLAPPED));
ovlp[i].Offset = i * MAX_READ;
ovlp[i].OffsetHigh = 0;
arrEvt[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
ovlp[i].hEvent = arrEvt[i];
// 记录每次读取的字节数,在ReadFile里面,此时是重叠结构,返回读取到的字节不准确(多数返回0),所以在这里记录
// 或者使用ReadFileEx+完成例程,在里面获取读取到的字节数
if (i == n - 1)
{
bufInfo.arrBytesRead[i] = dwSize % MAX_READ;
ZeroMemory(bufInfo.arrBuf[i], MAX_READ);
}
else
bufInfo.arrBytesRead[i] = MAX_READ;
bRet = ReadFileEx(hReadFile, bufInfo.arrBuf[i], MAX_READ, &ovlp[i], NULL);//最后一个参数就是指向一个完成例程函数的指针
//bRet = ReadFile(hReadFile, bufInfo.arrBuf[i], MAX_READ, NULL, &ovlp[i]);
if (!bRet)
{
if (GetLastError() != ERROR_IO_PENDING)//ERROR_IO_PENDINGIO等待 表示 这次操作没有立即完成(不算文件读取错误)
{
Sleep(10);
CloseHandle(arrEvt[i]);
i--;
continue;
}
}
}
// 最后两个参数 TRUE INFINITE 无限等待所有重叠操作的事件有信号到来,此时文件读取完成
WaitForMultipleObjects(n, arrEvt, TRUE, INFINITE);
// 到此,所有的文件读取已经完成
for (int i = 0; i < n; i++)// 关闭所有事件对象句柄
CloseHandle(arrEvt[i]);
HANDLE hWriteFile = CreateFile(pWriteFile,
GENERIC_WRITE, // 写文件模式
FILE_SHARE_WRITE,
0,
OPEN_ALWAYS,
FILE_FLAG_OVERLAPPED,// 使用重叠IO模式写文件
0);
if (hWriteFile == INVALID_HANDLE_VALUE)
return;
DWORD nBytesWrite;
for (int i = 0; i < n; i++)
{
ZeroMemory(&ovlp[i], sizeof(OVERLAPPED));
ovlp[i].Offset = i * MAX_READ;
ovlp[i].OffsetHigh = 0;
arrEvt[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
ovlp[i].hEvent = arrEvt[i];
bRet = WriteFileEx(hWriteFile, bufInfo.arrBuf[i], bufInfo.arrBytesRead[i], &ovlp[i], NULL);
//bRet = WriteFile(hWriteFile, bufInfo.arrBuf[i], bufInfo.arrBytesRead[i], &nBytesWrite, &ovlp[i]);
if (!bRet)
{
if (GetLastError() != ERROR_IO_PENDING)
{
Sleep(10);
CloseHandle(arrEvt[i]);
i--;
continue;
}
}
}
WaitForMultipleObjects(n, arrEvt, TRUE, INFINITE);
// 到此,所有文件写入完毕
CloseHandle(hReadFile);
CloseHandle(hWriteFile);
for (int i = 0; i < n; i++)
{
delete[] bufInfo.arrBuf[i];
CloseHandle(arrEvt[i]);
}
}
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
NomalReadWrite(L"H:\\setup1.exe", L"h:\\test\\setup.exe");
//MoreOverlapdReadWrite(L"H:\\setup1.exe", L"h:\\test\\setup.exe");
return 0;
}
/***********重叠结构****************************
typedef struct _OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
} DUMMYSTRUCTNAME;
PVOID Pointer;
} DUMMYUNIONNAME;
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
******************************************/