본문 바로가기
C & C++/C & C++

대용량 파일 열기

by izen8 2011. 3. 3.
반응형

void CFileOpenTestDlg::OnButton1()
{
 // TODO: Add your control notification handler code here
   // 파일 열기

 __int64 nFileSize;
 DWORD dwFileSizeLow, dwFileSizeHigh;
 HANDLE hFile;
 CString strTemp;
 CString pszObjectFile;
 UINT nNumTotal = 0;


 // 파일 형식란을 defaule 값으로 모든 파일로 설정.
 CFileDialog oFileDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_NOCHANGEDIR, _T("All Files(*.*)|*.*||"));
 
 if(oFileDlg.DoModal() == IDOK)
 {
  // 파일 경로(파일명 포함), 파일명, 파일 사이즈를 구한다.
 
  pszObjectFile = oFileDlg.GetPathName();

  hFile = ::CreateFile(pszObjectFile, GENERIC_READ , FILE_SHARE_READ, NULL,
   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

  if( hFile == INVALID_HANDLE_VALUE )
  {
   CString strErrMsg;
   LPVOID lpMsgBuf;
   FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
       NULL,
       GetLastError(),
       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
       (LPTSTR) &lpMsgBuf,
       0,
       NULL
       );
   // Process any inserts in lpMsgBuf.
   // ...
   // Display the string.
   strErrMsg.Format(_T("CreateFile() 1 fail!.ErrorCode=0x%xErrorMsg=%s"), ::GetLastError(), lpMsgBuf);

   // Free the buffer.
   LocalFree( lpMsgBuf );  
 
   return;
  }
 
  dwFileSizeLow = ::GetFileSize( hFile, &dwFileSizeHigh );

  if( (dwFileSizeLow != 0xFFFFFFFF)  ||  GetLastError() == NO_ERROR )
   nFileSize = (__int64) dwFileSizeHigh << 32  |  dwFileSizeLow;

  strTemp.Format( _T("%I64d"), nFileSize );
 
  ULONG lpReadNum = NULL;
 
  TCHAR szDataBuf[1024] = {0};

  BOOL bResult;

  while( 1 ) {
   bResult = ::ReadFile( hFile, szDataBuf, 1024, &lpReadNum, NULL );

   if( bResult ) {

    if( lpReadNum != 0 ) {
     nNumTotal += lpReadNum;
    }
    else {
     AfxMessageBox("EndFile");
     break;
    }

   }
   else {
    AfxMessageBox("ReadFailure");
     break;
    }
   }
  }
 
 strTemp.Format("before %I64d, after %u", nFileSize, nNumTotal);
 AfxMessageBox(strTemp);
 ::CloseHandle(hFile);
}


대용량(2GB 이상) 파일을 열어야 할 경우 파일의 크기를 int 형으로 받으면(32bit OS) int 형의 범위를 벗어나서 오버플로우를 일으키게 된다.
고로 제대로 된 파일 크기를 인식하지 못한다.
따라서 DWORD 형으로 크기를 받고 비트연산을 하여 __int 형에 넣으면 제대로 된 파일의 크기를 얻을 수 있다.
점점 대용량 파일이 많아지는 추세이니,,,알아두면 좋을 듯,,,

이거 만들때는 고생했는데,,,이렇게 쓰고 나니,,,얼마 안된다 ㅡㅡ;;;


반응형

댓글