본문 바로가기
프로그래밍/C++

INI 파일이란

by 건우아빠유리남편 2009. 12. 29.
반응형

1. INI 파일이란...

간단히 말하면 응용 프로그램이 실행될 때 필요한 초기화 정보를 담고있는 파일 (INItialization file) 이다. 16 bit 윈도우즈 응용 프로그램들은 대부분 실행파일명과 동일한 이름을 가진 INI 파일을 가지고 있으며 윈도우즈 자신도 win.ini 라는 초기화 파일을 가지고 있다. 아스키 파일이므로 일반 텍스트 편집기로 쉽게 내용을 확인할 수 있고 그 속에 담긴 정보의 의미를 정확히 이해할 수 있는 경우라면 간단히 수정할 수도 있다. 보통 윈도우즈 디렉토리나 응용 프로그램이 설치된 디렉토리에 존재한다.

2. INI 파일에는 무엇을 기록하는가?

꼭 무엇을 기록해야 하는가는 중요치 않다. 프로그래머가 필요하다고 생각되는 정보는 무엇이든 기록할 수 있다. 일반적으로는 최근에 불러왔던 파일들의 목록, 최근에 실행되었을 때의 윈도우 위치와 모양등을 기록하며 그 외에는 프로그램에 따라 달라진다. 예를 들어, 우리가 사용하는 DevStudio는 프로그램 실행시 이전에 종료하기 전 작업상태 그대로를 유지하여 시작할 수 있는 옵션이 있는데 이런 일에도 사용할 수 있는 것이다.

3. INI 파일의 구성

INI 파일은 다음의 세부분으로 구성된다. 섹션 (section), 키 (key), 값 (value)
예를들어 어떤 게임 프로그램에서 상위 10등 이내에 든 사람의 이름을 ini 파일에 기록한다면 이런 식이 될 것이다.

[SCORE] <--- 섹 션: SCORE
1등=밤사람 <--- 키: 1등, 값: 밤사람
2등=홍길동 <--- 키: 2등, 값: 홍길동
3등=나삼등 <--- 키: 3등, 값: 나삼등
... ...

4. INI 파일에서 정보를 가져오기.

WIN 32 API는 INI 파일에서 정보를 읽어내는 것과 관련 4개의 함수를 제공한다. 아래에 함수들의 원형이 소개되어 있다.

DWORD GetProfileString( LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault,
	LPTSTR lpReturnedString, DWORD nSize );
UINT GetProfileInt( LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault );
DWORD GetPrivateProfileString( LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize, LPCTSTR lpFileName );
UINT GetPrivateProfileInt( LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault, LPCTSTR lpFileName );

크게 2가지로 분류해 볼 수 있을 것이다. 하나는 데이터 타입으로 구분된다는 점이고 또 하나는 private이냐 아니냐 하는 점이다.
GetProfileString()과 GetProfileInt()는 win.ini 파일에, GetPrivateProfileString()과 GetPrivateProfileInt()은 프로그래머가 정의한 ini 파일에 정보를 읽고 쓴다. 함수들의 인자를 자세히 살펴보면 바로 파일명을 전달하는 인자가 있고 없는 차이뿐이다.

API 라이브러리나 DevStudio의 온라인 도움말을 참조하면 함수들의 인자에 대한 자세한 설명이 나와있다. 여기서는 앞에서 예로 들었던 게임점수 기록을 가지고 간단히 설명하겠다.

strName = GetPrivateProfileString( "SCORE", "1등", "기록없음", "c:\\game\\score.ini" );

이것은 "c:\game\score.ini" 파일을 열고 "SCORE" 섹션중 "1등" 이라는 키에 기록되어 있는 값을 읽어 strName 이라는 변수에 저장하라는 말이다. GET 함수들은 읽어낸 값(문자열의 경우 null종료문자를 뺀) 반환한다. 만일 해당 파일이나 섹션, 키가 존재하지 않거나 기록된 값이 없다면 기본값으로 "기록없음"을 사용하라는 뜻이다.
추가로 파일명에 경로가 사용되지 않으면 프로그램은 해당 파일을 윈도우즈 디렉토리에서 찾게 된다. 물론 경로가 쓰인다면 해당 경로에서 파일을 찾게된다.

nScore = GetPrivateProfileInt( "SCORE", "1등점수", 0, "score.ini" );

이것은 읽어내야할 값이 정수라는 차이 밖에 없다. 나머지는 string을 대상으로한 함수와 동일하다.

strName = GetProfileString( "SCORE", "1등", "기록없음" );
nScore = GetProfileInt( "SCORE", "1등점수", 0 );

여기엔 파일명이 없다. 작업 대상이 되는 파일이 무조건 win.ini가 되기 때문이다. 대개는 윈도우즈가 설정한 값들을 이용하기 위해 사용하지만 여러분이 원한다면 개인적인 정보도 win.ini에 두고 사용할 수 있다.

5. INI 파일에 정보를 기록하기.

WIN 32 API는 INI 파일에 정보를 기록하는 것과 관련 2개의 함수를 제공한다. 아래에 함수들의 원형이 소개되어 있다.

BOOL WritePrivateProfileString( LPCTSTR lpAppName, LPCTSTR lpKeyName,
	LPCTSTR lpString, LPCTSTR lpFileName );
BOOL WriteProfileString( LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString );

읽기함수들과 달리 쓰는 함수엔 정수형을 위한 함수가 없다. 모두 문자로 처리되기 때문이고 어차피 읽기함수가 그것을 문자로 읽을 것인지 아니면 숫자로 읽을 것인지를 처리해 주므로 아무 문제가 없다.

WritePrivateProfileString( "SCORE", "1등", strName, "c:\\game\\score.ini" );
WritePrivateProfileString( "SCORE", "1등점수", strScore, "c:\\game\\score.ini" );

이것은 "c:\game\score.ini" 파일을 열고 "SCORE" 섹션중 "1등" 키에는 "strName" 변수에 저장된 값을, "1등점수" 키엔 "strScore" 변수에 저장된 값을 기록하라는 뜻이다. 물론 숫자형태의 점수는 문자열로 먼저 변환시켜야 할 것이다. 여기서도 nScore를 strScore로 변형했다.
win.ini를 대상으로한 함수는 설명하지 않아도 되겠죠?

6. 기타

① 정수형이 아닌 수의 처리는 어떻게 할까? 예를들어 float형이라든가 하는...
API가 완벽하다고는 할 수 없지만 대개는 제공하지 않는 함수가 있다면 분명히 다른 방법이 있기 때문이다. 이 경우에도 처음부터 숫자 데이터를 읽지말고 문자열로 읽어낸 후에 원하는 변수형으로 전환시키면 된다. 그럼 문자를 숫자로 어떻게...? 게으르기는! C 또는 C++의 문자열처리 함수(또는 클래스)를 찾아보~아.

② 새로운 섹션이나 키를 만들려면...
값을 기록하는 함수들을 그냥 사용하면 된다. 쓰기 함수들은 기록하려는 섹션이나 키가 없다면 새로 만들어서 값을 기록하기 때문이다.

③ 기록했던 섹션을 지우려면...
특별히 섹션을 지우는 함수는 없다. 그러나 방법은 있다. 기록함수에서 키네임을 전달하는 두번째 인자의 값으로 null을 주면 된다. 이렇게...

WritePrivateProfileString( "SCORE", NULL, "", "score.ini" );

INI 파일의 모든 섹션을 순서대로 정리하고 싶다면 기록하기 전에 이 방법으로 지우고 나서 기록을 하면 될 것이다.

④ 섹션이나 키를 지정할 때 대소문자를 구분해야 하는가?
섞어써도 상관없다. 즉, 대소문자를 구분하지 않는다.

***************************************************************************************

private과 아닌 함수의 차이는 win.ini에는 private가 없는걸 쓰고 자기가 짠프로그램에는 있는걸

쓰면 된다고 DevStudio에 나와 있단다..

***************************************************************************************

1. 응용 프로그램의 INI 파일 : 표준 INI (standard INI)

Win 95' 이래 INI 파일의 사용은 윈도우즈 레지스트리로 대체되었지만 탐색기로 윈도우즈 디렉토리를 열어보면 *.ini 파일을 많이 볼 수 있는데 그것은 아직도 INI 파일이 사용되고 있다는 얘기다.

윈도우즈 디렉토리에 있는 INI 파일들의 이름은 대개 응용 프로그램의 이름과 같다. 예를들어 넷스케이프를 사용하고 있다면 그곳에서 netscape.ini 파일을 볼 수 있을 것이다.

응용 프로그램의 INI 파일은 보통 윈도우즈 디렉토리에 만들어지며 그 응용 프로그램의 실행에 관련된 정보를 기록하여 두었다가 실행시에 사용하게 된다. 간단한 예를 든다면 툴바의 위치나 응용 프로그램이 최근에 실행될 때의 창의 크기나 상태 그리고 최근에 열었던 파일의 목록등을 기록하는 것이다.

MFC를 사용하여 만든 응용 프로그램에서는 CWinApp 클래스가 응용 프로그램의 INI 파일을 관리하는 몇 개의 멤버함수들을 제공해 주는데 특별한 지시가 없는 한 응용 프로그램의 INI 파일을 대상으로 정보를 기록하거나 읽어오게 되며 응용 프로그램이 처음 실행될 때 윈도우즈 디렉토리에 만들어지게 된다.

2. 읽고 쓰는 함수들

앞서 말했듯이 MFC의 CWinApp 클래스엔 다음과 같은 멤버함수들이 있다.


UINT    GetProfileInt( LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault );
CString GetProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry,
                          LPCTSTR lpszDefault = NULL );

BOOL WriteProfileInt( LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue );
BOOL WriteProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue );

사용법은 간단하다. 모두 3개씩의 인자를 가지고 있는데 처음 두개중 lpszSection은 섹션명을, lpszEntry는 해당 섹션의 키를 지정한다. 세번째 인자는 읽는 함수들의 경우 INI 파일이 없거나 있더라도 지정된 섹션이나 키가 없을경우 기록된 값 대신 사용할 디폴트 값이며 쓰는 함수들의 경우엔 해당 키에 기록할 값을 넣어주면 된다.
함수들의 리턴값은 쓰는 함수들의 경우 쓰기가 성공하면 '0'이 아닌 값, 실패하면 '0'이 되고 읽는 함수들의 경우 읽어낸 또는 디폴트로 지정한(읽기를 실패한 경우) 정수 또는 문자열이다.

※ 참고:
값을 기록하기 위해 지정한 섹션이나 키가 존재하지 않는다면 새로 만들어진다. 만약 이미 만들어진 섹션이나 키를 지우려면 WriteProfileString() 함수의 세번째 인자로 NULL을 지정하면 된다. 그리고 섹션이나 키 네임은 대소문자를 구분하지 않는다.

3. 지정된 INI 파일 바꾸기

CWinApp 클래스의 데이터 멤버 중엔 m_pszProfileName이 있는데 바로 이 변수에 응용 프로그램이 사용할 INI 파일명이 담겨 있다.

   public:   const char* m_pszProfileName;

만약 응용 프로그램이 사용할 INI 파일의 경로나 이름을 바꾸고 싶다면 이 변수에 원하는 경로와 파일명을 넣어주면 되는데 그 전에 해야할 일이 있다.

m_pszProfileName은 위에 보인대로 char형 포인터 변수이다. 응용 프로그램이 시작되고 CWinApp 가 생성되면 이 변수가 가리키는 문자열을 저장할 메모리는 힙 상에 동적으로 할당된다. 따라서 새로 문자열을 지정하려면 먼저 이전에 할당된 메모리를 해제하고 다시 메모리를 할당해야 한다. 다음이 그 과정이다.


   // 메모리 해제
   free( (void*) m_pszProfileName );

   // 재 할당
   m_pszProfileName = _tcsdup( _T( "c:\\myApp\\myApp.ini" ));

첫번째 메모리 할당은 CWinApp 클래스의 InitInstance()가 실행되기 전에 이루어지므로 다시 지정하기 위한 위의 두 줄은 InitInstance() 멤버에 넣어주면 될 것이다.

이 때 주의할 점은 만약 InitInstance()에 응용 프로그램의 INI 파일을 사용하는 코드가 있다면 그 코드의 앞에서 재지정이 이루어져야 한다는 것이다. 그렇지 않을 경우엔 당연히 INI 파일에서 쓰거나 읽은 데이터가 엉뚱한 것이 될 수도 있다.

예를든다면, InitInstance() 함수엔 응용 프로그램이 최근에 열었던 파일목록을 읽어오기 위해 CWinApp 클래스의 LoadStdProfileSettings() 멤버를 둘 수 있는데 이 함수가 호출된 뒤에 응용 프로그램의 INI 파일을 바꾸어버리면 응용 프로그램을 종료할 때 다시 기록되는 최근 파일목록은 어떻게 변경되든 상관없이 다시 프로그램이 실행될 때 읽혀지지 않을 것이다. 


반응형

댓글