*스레드 기반으로 파일 I/O하기.
Thread에서 사용할 파일 I/O에 관한 정보구조체
typedef struct _COPY_FILE{
TCHAR szSrcFile[MAX_PATH+_MAX_FNAME];
TCHAR szDestFile[MAX_PATH+_MAX_FNAME];
LPVOID pDlg;
}
-pDlg를 넣는 이유는? WorkerThread가 실행되기 전에 Dialog를 만들어두고 그 대화상자의 주소를 넘겨주기 위해서. (ProgressBar Dialog는 Main Dialog에 속해있어야한다. Thread한테 속해있는것이 아니라.)
*Thread에서 사용할 함수
DWORD WINAPI ThreadCopyFile(LPVOID pParam){
COPY_FILE File;
memcpy(&File, pParam, sizeof(COPY_FILE));
CString tmp = _T("");
HANDLE hFileSource = NULL,hFileDest = NULL;
DWORD dwDisplayProgressValue = 0;
DWORD dwCurrentProgressValue = 0;
CThreadDlg* pDlg = (CThreadDlg*)File.pDlg;
//1. 원본파일 읽기모드 로 열기
hFileSource = ::CreateFile(File.szSrcFile,
GENERIC_READ, //read
FILE_SHARE_READ, //읽기모드 공유허용
NULL, //보안속성없음
OPEN_EXISTING, //존재하는 파일 열기
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFileSource == INVALID_HANDLE_VALUE){
tmp.Format(_T("원본 파일을 여는데 실패했습니다.\nError Code [%d]"),::GetLastError());
AfxMessageBox(tmp);
pDlg->ShowWindow(SW_HIDE);
return FALSE;
}
//2. 대상파일 쓰기모드로 열기
hFileDest = ::CreateFile(File.szDestFile,
GENERIC_WRITE, //쓰기모드
0, //공유안함
NULL, //보안속성없음
CREATE_NEW, //새로생성
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFileDest == INVALID_HANDLE_VALUE){
tmp.Format(_T("복사본 파일을 생성하는데 실패했습니다.\nError Code [%d]"),::GetLastError());
AfxMessageBox(tmp);
::CloseHandle(hFileSource);
pDlg->ShowWindow(SW_HIDE);
return FALSE;
}
/*
파일복사과정....
src의 한 block을 dest에 write. 그리고 write하는순간 Progress를 SetPos한다.
*/
//3. loop을 돌면서 파일내용을 복사한다.
LARGE_INTEGER llFileSize; //DWORD두개로 값이 구성 64bit임. 이유는 고용량 하드를 인식
llFileSize.QuadPart = 0;
LONGLONG llTotalReadSize = 0; //64비트데이터
DWORD dwReadSize = 0, dwWriteSize = 0;
BOOL bResult = FALSE;
BYTE byBuffer[PAGE_SIZE];
if(!::GetFileSizeEx(hFileSource,&llFileSize)){
AfxMessageBox(_T("원본 파일의 크기를 알 수 없습니다."));
::CloseHandle(hFileSource);
::CloseHandle(hFileDest);
pDlg->ShowWindow(SW_HIDE);
return FALSE;
}
for(LONGLONG i = 0 ; i < llFileSize.QuadPart ; i += dwReadSize){
if(pDlg->m_bCancel){
break;
}
::ZeroMemory(byBuffer,PAGE_SIZE);
bResult = ::ReadFile(hFileSource,byBuffer,PAGE_SIZE,&dwReadSize,NULL);
if( !bResult){
tmp.Format(_T("원본 파일을 읽는 데 실패하였습니다. Error Code [%d]"),::GetLastError());
AfxMessageBox(tmp);
break;
}
//if EOF then finish loop
else if(bResult&& dwReadSize == 0){
break;
}
///////////////////////////////////////////////////////////////////////
//복사완료 비율계산
llTotalReadSize += dwReadSize;
dwCurrentProgressValue = (int)(llTotalReadSize * 100 / llFileSize.QuadPart);
if(dwDisplayProgressValue != dwCurrentProgressValue){
pDlg->SetPos(dwCurrentProgressValue);
dwDisplayProgressValue =dwCurrentProgressValue;
}
if(!::WriteFile(hFileDest,byBuffer,dwReadSize,&dwWriteSize,NULL)){
tmp.Format(_T("대상 파일을 저장하는데 실패하였습니다. Error Code [%d]"),::GetLastError());
AfxMessageBox(tmp);
}
}
if(pDlg->m_bCancel){
AfxMessageBox(_T("Cancel Copy."));
}else{
AfxMessageBox(_T("Complete Copy."));
}
::CloseHandle(hFileSource);
::CloseHandle(hFileDest);
pDlg->ShowWindow(SW_HIDE);
return TRUE;
}
댓글