5. MFC Programming : 쉽게 배우는 MFC 윈도우 프로그래밍(CH 7)
공부하는 도중 정리하면서 글을 작성하는 것이라 두서가 없을 수 있습니다. 작성된 코드는 실습하면서 작성되는 코드들로 전체적인 맥락을 모르고 있으면 이해하기 어려울 수 있음을 미리 밝힙니다.
파일 입출력은 자주 사용되는 기능들 중 하나이다. 비단 텍스트 파일들을 비롯한 컴퓨터의 기억장치에 저장되는 파일뿐만 아니라 소켓 프로그램, 인터넷 등 데이터를 내려 받는 대부분이 기본적인 파일 입출력 기능에 근간을 두고 있어서 파일을 열고(Open), 읽고(Read), 쓰고(Write), 입출력 위치를 탐색 및 변경하고(Seek), 닫는 것(Close)을 아는 것은 중요하다.
MFC 프로그램에서는 이러한 기능을 CFile 클래스를 제공하고 있다. 또한 직렬화 기능을 제공하는 데, 이는 CArchieve 클래스 객체를 이용하여 연산자를 이용하여 파일 입출력을 처리한다는 점에서 CFile 클래스를 사용한 입출력보다는 간단하게 프로그래밍할 수 있다.
CFile 클래스로 파일을 읽어오기 위해서는 우선 파일을 열어주어야 한다. CFile::Open()으로 해당 작업을 수행할 수 있다. 다음과 같이 사용하면 된다.
try{
CFile file(_T("mytest.txt"), CFile::modeReadWrite);
} catch (CFileException* e){
e->ReportError();
e->Delete();
}
//Mode 종류
//CFile::modeCreate : 파일을 무조건 생성
//CFile::modeNoTruncate : modeCreate와 같이 사용, 같은 이름의 파일이 있는 경우 그 파일을 열음
//CFile::modeRead : 읽기 모드
//CFile::modeReadWrite : 읽기 쓰기 모드
//CFile::modeWrite : 쓰기 모드
//CFile::shareDenyNone : 파일에 대한 읽기와 쓰기를 다른 프로세스에 허용
//CFile::shareDenyRead : 다른 프로세스가 파일을 읽는 것을 금함
//CFile::shareDenyWrite : 다른 프로세스가 파일을 쓰는 것을 금함
//CFile::shareExclusive : 다른 프로세스가 파일을 읽거나 쓰는 것을 금함
CFile 객체는 파일을 닫는 기능을 제공한다. CFile::Close()로 닫을 수 있으나, 메모리에서 해제될 때 자동으로 호출되어서 항상 명시적으로 Close() 함수를 사용하지는 않아도 된다. 다만 CFile 하나의 객체만으로 여러 파일을 열고 닫는 경우 명시적으로 작업해줄 필요가 있다.
다음은 CFile::Read(), CFile::Write(), 즉 파일을 읽고 쓰는 기능에 대해서 다룰 것이다.
UINT CFile::Read(void* lpBuf, UINT nCount) // 어디 저장, 얼마만큼 읽어 -> 읽은 바이트수 반환
void CFile::Write(const void* lpBuf, UINT nCount) //어디에서, 얼마만큼 써
CFile::Seek() 함수는 파일 포인터를 임의 위치로 옮겨준다. 함수의 형식은 다음과 같다.
UNlONGLONG CFile::Seek(LONGLONG lOff, UINT nFrom)
LONG CFile::Seek(LONG lOff, UINT nFrom)
/*
nFrom :
CFile::begin : 파일의 처음 위치
CFile::current : 현재 팡ㄹ 포인터 위치
CFile::end : 파일의 끝 위치
*/
다음은 그 외의 유용한 CFile 클래스 맴버 함수를 정리한 것들이다.
CFile::GetLength(), SetLength() : 파일 현재 크기 반환, 설정
CFile::GetPosition() : 현재 파일 포인터 위치 반환
CFile::LockRange(), UnlockRange() : 파일의 일정 영역을 잠그거나, 해제, 따른 프로세스의 접근을 막는다
CFile::GetFilePath(), CFile::GetFileName() : 파일 전체 경로를 반환
CFile에서 파생되는 또는 연관성 있는 클래스에는 다음과 같은 것들이 있다.
- CMemFile : 디스크가 아닌 메모리에 존재하는 파일을 생성할 수 있음 (CFile 자식 클래스)
- CStdioFile : 줄 단위로 읽고 쓸 수 있는 기능을 제공 (CFile 자식 클래스)
- CFileFind : 파일 검색 기능을 제공, 차후 다룰 CFtpFileFind, CGopherFileFind 클래스와 관련됨
Document-View Architecture는 MFC 응용 프로그램에서 중요한 개념이다. 직렬화를 위해서는 이 구조로 프로그램을 짤 필요가 있다. Document는 View 즉 사용자가 보고 컨트롤 하는 인터페이스와 파일 사이를 매개하는 중간자 성격을 지닌다. 이처럼 Document-View Architecture로 프로그램을 짜면 좋은 점은, 하나 서로 다른 기능을 가진 클래스로 나누어 프로그래밍을 함으로써 차후 유지, 보수에 유리하고, 둘 Document 하나에 여러 View가 존재하는 모델을 구현하기 쉽다. Visual Studio는 Document-View Architecture를 쉽게 구성할 수 있도록 프로젝트 생성에 템플릿을 선택할 수 있도록 하였다.
CArchieve 기능을 사용하더라도 결국 파일을 여닫는 것은 CFile 클래스가 해주어야 하므로 완전히 없애는 것은 불가하다.
CArchive::CArchive(CFile* pFile, UINT nMode, int nBuffSize=4096, void* lpBuff)
//데이터를 저장하는 곳(파일), 모드, 클래스 내부에서 사용할 버퍼 사이즈,
사용자 정의 버퍼의 주소 값(NULL시 힙 영역에서 자동으로 설정)
//직렬화 가능한 데이터 타입 : BOOL, BYTE, DWORD, LONG, char, wchar_t, int, float, double
//RECT, POinT, SIZE, CRect, CPoint, CSize, CString, CTime, CTimeSpan, COleVariant, COleCurrency,
//COleDateTime, COleDataTimeSpan
Document-View Architecture 구조를 그림으로 그리면 다음과 같다.
코드로 구조를 보고 싶다면 Visual Studio에서 MFC 앱 -> document type : Single document로 설정하고 코드를 천천히 보기를 바란다. 코드 전체를 다루기에는 코드의 양이 너무 많다. 이 것으로 글을 마친다.