E D R S I H C RSS
ID
Password
Join
빛을 느낄 수 있는건 어둠을 알기 때문이다. - 송용완



Contents

1 시작하며
2 Serialize?
3 그럼 Serialize()는 언제 호출되는가?
4 CArchive?
5 주의사항
6 마치며

1 시작하며 #

참고로 이미 Doc/View 구조는 알고있다고 생각하고 진행하도록 하겠습니다. 모르겠다하시는 분은 수업시간에 질문하시거나 책을 통해서 복습해주시기 바랍니다.

2 Serialize? #

CObject는 모든 MFC 클래스의 기본 부모 클래스입니다. 이 클래스 맴버 중에는 Serialize()라는 메소드가 선언되어있는데, 이 메소드는 현재 객체의 내용을 디스크나 다른 저장공간에 기록하거나 읽어들이는 역할을 수행합니다. 당연히 CObject로 부터 상속받은 객체들은 자신을 저장하는 수단으로 이 메소드를 사용하는 것이 좋겠죠.

당연히 CDocument도 예외는 아닐 겁니다. 맨처음 new메뉴에서 생성한 MFC 초기 프로젝트는 내부적으로 이미 save/load 부분을 메뉴에 추가해놓은 상태라고 보면 됩니다. 클래스 위저드를 열어서 Doc 클래스의 맴버함수를 보면 Serialize() 가 기본적으로 추가되어있는 것을 볼 수 있습니다. 이 맴버 함수의 내용을 잠깐 보면 다음과 같습니다.
void CMFCExam0Doc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}
todo 주석을 참조하면 저장과 읽기 작업에 대한 코드를 넣으라는 것을 알 수 있습니다. 바로 이 부분에다가 CDocument(위 코드에서는 CMFCExam0Doc)의 내용을 디스크에 저장하고 읽는 코드를 넣어주면 됩니다.

3 그럼 Serialize()는 언제 호출되는가? #

이것은 MFC 내부적으로 숨겨져있습니다. MFC 프레임워크 내부에서는 기본적으로 ID_FILE_NEW, ID_FILE_SAVE, ID_FILE_OPEN, ID_FILE_SAVE_AS라고 하는 메뉴항목이 첨가되어있는데, 이것은 왠만한 프로그램들이라면 모두 가지고 있는 메뉴겠지요. 각 항목을 선택하면 다음과 같은 순서대로 메소드들이 실행됩니다. (몰론 기본적으로 코드에서는 보이지 않습니다.)
ID_FILE_NEWCWinApp::OnFileNew() → 신규 CDocument 객체 생성 → CDocument::OnNewDocument()
ID_FILE_OPENCWinApp::OnFileOpen() → 신규 CDocument 객체 생성 → CDocument::OnOpenDocument() → CDocument::Serialize()
ID_FILE_SAVECWinApp::OnFileSave() → CDocument::OnSaveDocument() → CDocument::Serialize()
ID_FILE_SAVE_ASCWinApp::OnFileSaveAs() → 새로운 화일명 입력 → CDocument::OnNewDocument()

위 '기본' 실행이 맘에 안든다면 각각의 맴버 함수를 오버라이딩하면 됩니다. 위 실행순서를 보면, 화일을 열거나 저장할때는 맨 마지막에 Serialize()가 호출되는 것을 볼 수 있습니다.

4 CArchive? #

앞서 보여주었던 Serialize() 메소드에서 인자로 CArchive라는 객체의 참조가 넘겨져오는 것을 볼 수 있습니다. 이것은 저장하거나 읽어들일 화일 그 자체를 나타냅니다. CArchive는 고맙게도 기존의 ANSI C에서 사용했던 함수와 매치되는 메소드를 가지고 있습니다. 다음 표를 참조하세요. (인자는 생략했습니다. MSDN 참조하시길...)
CArchiveANSI C
Read()fread()
Write()fwrite()
ReadString()fgets()
ReadString()fputs()

다음 코드는 CMFCExam0Doc에 m_Str1, m_Str2이라는 STL string 맴버 변수가 있다고 가정하고 만든 예제코드입니다.
void CMFCExam0Doc::Serialize(CArchive& ar)
{
    if (ar.IsStoring()) 
    { 
        // TODO: add storing code here 
        ar.WriteString(m_Str1.c_str());
        ar.WriteString("\n");
        ar.WriteString(m_Str2.c_str());
        ar.WriteString("\n");
    } 
    else 
    { 
        // TODO: add loading code here 
        CString tmpStr; 
        ar.ReadString(tmpStr);
        m_Str1 = string((LPCTSTR)tmpStr);
        ar.ReadString(tmpStr); 
        m_Str2 = string((LPCTSTR)tmpStr); 
    } 
}

위 예제에서 m_Str1, m_Str2의 순서대로 적고 있음에 주의하시기 바랍니다. 일반 fread/fwrite 함수 사용과 거의 같다는 것을 알 수 있습니다. 만일 CArchive 객체를 사용하는 것이 영 그렇다고 느끼시는 분(일반적인 C 코딩에 익숙하신 분이나 자신의 라이브러리에서 이미 화일 저장함수가 만들어져 있을 경우)는 CDocument::OnOpenDocument()/CDocument::OnSaveDocument()를 오버라이딩해서 코드를 작성하시면 됩니다. (기본적으로 부모의 매소드를 다시한번 호출하는 것을 볼 수 있는데, 이는 삭제해주시면 됩니다. 왜냐하면 Serialize()를 자동으로 동작시키는 부분이 여기거든요.)

5 주의사항 #

  • CArchive는 단방향으로밖에 읽을 수 없습니다. 즉, 한번 읽어들였으면 fseek()와 같은 함수로 되감기를 할 수 없다는 뜻입니다. 이런 처리가 필요하다면 CDocument::OnOpenDocument() / CDocument::OnSaveDocument()를 오버라이딩해서 직접 화일 입출력을 하는 방법을 택해야합니다.
  • EOF 채크방법은 입출력 처리시 Read(), Write()함수는 지정한 버퍼보다 적게 읽혀졌을 경우, ReadString(), WriteString()은 반환값이 NULL일 경우를 채크하시면 됩니다.

6 마치며 #

간단히 MFC에서 화일을 저장하고 읽는 부분에 대해서 적어보았습니다. 수업때 구체적으로 예를 들어 설명하도록 하죠. 그럼...

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2010-10-28 12:42:52
Processing time 3.3984 sec