C++多线程复制文件
使用文件读写复制问文件的线程函数:
DWORD WINAPI CopyThread(LPVOID lpParam)
{
CCopyFileDlg *dlg=(CCopyFileDlg*)lpParam;
CFile file1(dlg->m_Src,CFile::modeRead);
CFile file2(dlg->m_Dest,CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate); //注意CFile::modeNoTruncate
char buff[1024*400]={0};
UINT read=file1.Read(buff,sizeof(buff));
DWORD Len=file1.GetLength();
DWORD Have=0;
while(read>0)
{
file2.Write(buff,read);
file2.SeekToEnd(); //移动文件指针,否则会覆盖
Have+=read;
PostMessage(dlg->m_hWnd,WM_READ,Len,Have);
read=file1.Read(buff,sizeof(buff));
}
return 0;
}
使用内存映射复制线程函数:
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
CCopyFileDlg *dlg=(CCopyFileDlg*)lpParam;
HANDLE hFile=CreateFile(dlg->src,GENERIC_READ | GENERIC_WRITE,PAGE_READONLY,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);
DWORD dwFileSizeHigh;
__int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
qwFileSize |= (((__int64)dwFileSizeHigh) << 32);
HANDLE hFile2=CreateFile(dlg->dest,GENERIC_READ | GENERIC_WRITE,PAGE_READWRITE,NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE)
{
TRACE("创建文件对象失败,错误代码:%d\r\n", GetLastError());
return 0;
}
HANDLE hFileMapping=CreateFileMapping(hFile, NULL,PAGE_READWRITE,0,qwFileSize,NULL);
HANDLE hFileMapping2=CreateFileMapping(hFile2, NULL,PAGE_READWRITE,0,qwFileSize,NULL);
if (hFileMapping || hFileMapping2 == NULL)
{
TRACE("创建文件映射对象失败,错误代码:%drn", GetLastError());
return 0;
}
SYSTEM_INFO sys;
GetSystemInfo(&sys);
DWORD dwGran =sys.dwAllocationGranularity; //系统粒度的大小
// 关闭文件对象
CloseHandle(hFile);
CloseHandle(hFile2);
// 偏移地址
__int64 qwFileOffset = 0;
// 块大小
DWORD dwBlockBytes = 100 * dwGran;
if (qwFileSize < 100 * dwGran)
dwBlockBytes = (DWORD)qwFileSize;
//int pos=dwBlockBytes*100/(qwFileSize*1.0);
while (qwFileSize > 0)
{
// 映射视图
LPBYTE lpbMapAddress = (LPBYTE)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS, (DWORD)(qwFileOffset >> 32), (DWORD)(qwFileOffset & 0xFFFFFFFF),dwBlockBytes);
LPBYTE lpbMapAddress2 = (LPBYTE)MapViewOfFile(hFileMapping2,FILE_MAP_ALL_ACCESS, (DWORD)(qwFileOffset >> 32), (DWORD)(qwFileOffset & 0xFFFFFFFF),dwBlockBytes);
if (lpbMapAddress && lpbMapAddress2 == NULL)
{
TRACE("映射文件映射失败,错误代码:%drn", GetLastError());
return 0;
}
memcpy(lpbMapAddress2,lpbMapAddress,dwBlockBytes);
// 撤消文件映像
UnmapViewOfFile(lpbMapAddress);
UnmapViewOfFile(lpbMapAddress2);
// 修正参数
qwFileOffset += dwBlockBytes;
qwFileSize -= dwBlockBytes;
if(qwFileSize < dwBlockBytes)
dwBlockBytes=qwFileSize;
}
CloseHandle(hFileMapping);
CloseHandle(hFileMapping2);
return 0;
}
另一个使用内存映射复制文件,限小于4G的文件
DWORD WINAPI MapThread(LPVOID lpParam)
{
CCopyFileDlg *dlg=(CCopyFileDlg*)lpParam;
HANDLE hFile=CreateFile(dlg->m_Src,GENERIC_READ,NULL,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL);
HANDLE hFile2=CreateFile(dlg->m_Dest,GENERIC_WRITE | GENERIC_READ,NULL,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE==hFile || INVALID_HANDLE_VALUE==hFile2 )
{
AfxMessageBox(_T("打开文件失败"));
return 0;
}
DWORD len=GetFileSize(hFile,0);
HANDLE hMapping=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
HANDLE hMapping2=CreateFileMapping(hFile2,NULL,PAGE_READWRITE,0,len,NULL);
if(hMapping==NULL || hMapping2==NULL )
{
AfxMessageBox(_T("CreateFileMapping失败"));
return 0;
}
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
DWORD dwFileOffsetLow=0;
DWORD dwGran=systemInfo.dwAllocationGranularity*10;
LPVOID pAdd=NULL,pAdd2=NULL;
DWORD read=0;
if(dwGran > len)
{
dwGran=len;
}
while(dwFileOffsetLow < len)
{
if(len-dwFileOffsetLow<dwGran)
read=len-dwFileOffsetLow;
else
read=dwGran;
pAdd=MapViewOfFile(hMapping,FILE_MAP_READ,0,dwFileOffsetLow,read);
pAdd2=MapViewOfFile(hMapping2,FILE_MAP_WRITE,0,dwFileOffsetLow,read);
if(NULL==pAdd || NULL==pAdd2)
{
AfxMessageBox(_T("MapViewOfFile失败"));
return 0 ;
}
else {
CopyMemory(pAdd2,pAdd,read);
dwFileOffsetLow+=read;
}
UnmapViewOfFile(pAdd);
UnmapViewOfFile(pAdd2);
PostMessage(dlg->m_hWnd,WM_READ,len,dwFileOffsetLow);
}
CloseHandle(hMapping);
CloseHandle(hMapping2);
return 0;
}
