INI (initialization file)

Get/WritePrivateProfileString 함수를 사용하면 ini파일을 읽고 쓰고 할 수 있다.

GetPrivateProfileString 함수에 대응하는 이름은 SetPrivateProfileString 일텐데 이런 이름의 함수는 없고
대신 WritePrivateProfileString 함수가 있다.

32-버전의 윈도우에서는 레지스트리를 사용할 것을 권장하지만 ini 파일은 메모장 같은 텍스트 편집기로 쉽게 편집이 가능하기에 환경설정 같은 것을 하기에 좋다.

 

Windows CE에는 없다

Windows CE로 포팅을 할 일이 있었는데 CE 5.0에 함수가 없었다.

인터넷을 검색해보니 '꼬마늑대의 골방' 블로그에서 이미 만들어 놓으신 것이 있었다.

그 외에도 크로스 플랫폼을 위해 SimpleIni 가 있었다.

 

약간 수정을 하여 사용하는 실행파일(예. some.exe)의 이름과 똑같은 ini파일(some.ini)에 알아서 사용하도록 하였다.

GetModuleFileName 함수를 이용하였고, 실행파일 이름이 바뀌면 자동으로 ini 파일도 바뀌도록 구현이 된 것.
꼬마늑대님이 만드신 함수는 파일이름을 받게끔 되어 있는데 따라서 그 인자는 사라짐.

<win_ce_ini.h>

  1. BOOL SaveToFile(LPCTSTR lpSection, LPCTSTR lpKeyName, LPCTSTR lpValue);

  2. BOOL LoadFromFile(LPCTSTR lpSection, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize);

 

<win_ce_ini.cpp>

  1. BOOL GetIniFilename(LPTSTR filename, DWORD dwLength)

  2. {

  3.     DWORD dw = GetModuleFileName(NULL,filename,dwLength);

  4.     if(dw!=0) {    // SUCCESS

  5.         filename[dw-3] = _T('i');

  6.         filename[dw-2] = _T('n');

  7.         filename[dw-1] = _T('i');

  8.  

  9.         return TRUE;

  10.     } else {

  11.         dw = GetLastError();

  12.         CString msg;

  13.         msg.Format(_T("Failed to Get INI Filename from module (%u)"), dw);

  14.         AfxMessageBox(msg, MB_OK | MB_ICONSTOP);

  15.         return FALSE;

  16.     }

  17. }

  18.  

  19. BOOL SaveToFile(LPCTSTR lpSection, LPCTSTR lpKeyName, LPCTSTR lpValue)

  20. {

  21.     CString out;

  22.     CString str;

  23.     TCHAR ch;

  24.     bool search = true;

  25.     bool app = false;

  26.     bool find = false;

  27.     int state = 0;

  28.     int idx = 0;

  29.  

  30.     // Get INI filename

  31.     TCHAR lpFileName[MAX_PATH] = {0};

  32.     if(!GetIniFilename(lpFileName, MAX_PATH)) return FALSE;

  33.  

  34.     FILE* fp = _tfopen(lpFileName, _T("rt"));

  35.  

  36.     // Open file

  37.     if (fp == NULL)

  38.         search = false;

  39.     else

  40.     {

  41.         while (1 == _ftscanf(fp, _T("%c"), &ch))

  42.             out += ch;

  43.         fclose(fp);

  44.     }

  45.  

  46.     for (int i = 0; search && i < out.GetLength(); i++)

  47.     {

  48.         ch = out[i];

  49.  

  50.         switch (state)

  51.         {

  52.         case 0:    // 첫글자

  53.             if (ch == _T(';'))

  54.                 state = 10;    // 주석 넘기기

  55.             else if (ch == _T('['))

  56.             {

  57.                 idx = 0;

  58.                 str = _T("");

  59.                 state = 20;       // AppName 비교

  60.             }

  61.             break;

  62.  

  63.         case 10:

  64.             if (ch == _T('\n'))

  65.                 state = 0;

  66.             break;

  67.  

  68.         case 20:

  69.             if (ch == _T(']'))

  70.             {

  71.                 if (str.Compare(lpSection) == 0)

  72.                 {

  73.                     idx = 0;

  74.                     str = _T("");

  75.                     state = 30;

  76.                     app = true;

  77.                 }

  78.                 else

  79.                     state = 10;

  80.             }

  81.             else

  82.                 str += ch;

  83.             break;

  84.  

  85.         case 30:    // AppName이 일치한 후

  86.             if (ch == _T('\n'))

  87.                 state = 31;

  88.             break;

  89.         case 31:

  90.             if (ch == _T('['))

  91.             {    // 다른 AppName이 시작한다면 여기에 삽입

  92.                 str.Format(_T("%s=%s\n"), lpKeyName, lpValue);

  93.                 out.Insert(i, str);

  94.                 search = false;

  95.                 find = true;

  96.             }

  97.             else if (ch == _T(';'))

  98.                 state = 30;

  99.             else

  100.             {

  101.                 idx = 0;

  102.                 str += ch;

  103.                 state = 32;

  104.             }

  105.             break;

  106.         case 32:

  107.             if (ch == _T('='))

  108.             {

  109.                 if (str.Compare(lpKeyName) == 0)

  110.                 {

  111.                     idx = 0;

  112.                     str = _T("");

  113.                     state = 40;

  114.                 }

  115.                 else

  116.                 {

  117.                     str = _T("");

  118.                     state = 30;

  119.                 }

  120.             }

  121.             else

  122.                 str += ch;

  123.             break;

  124.  

  125.         case 40: // KeyName이 일치한 후

  126.             if (ch == _T('\n'))

  127.             {

  128.                 out.Delete(i - str.GetLength(), str.GetLength());

  129.                 out.Insert(i - str.GetLength(), lpValue);

  130.                 search = false;

  131.                 find = true;

  132.             }

  133.             else

  134.                 str += ch;

  135.             break;

  136.         }

  137.     }

  138.  

  139.     if (!find) // AppName도KeyName도찾지못했다면

  140.     {

  141.         if (out.GetLength() > 0)

  142.         {

  143.             ch = out[out.GetLength()-1];

  144.             if (ch != _T('\n'))

  145.                 out += _T('\n');

  146.         }

  147.         if (!app)

  148.         {

  149.             str.Format(_T("[%s]\n"), lpSection);

  150.             out += str;

  151.         }

  152.         str.Format(_T("%s=%s\n"), lpKeyName, lpValue);

  153.         out += str;

  154.     }

  155.  

  156.     fp = _tfopen(lpFileName, _T("wt"));

  157.  

  158.     if (fp == NULL)

  159.         return FALSE;

  160.  

  161.     _ftprintf(fp, out);

  162.     fclose(fp);

  163.  

  164.     return TRUE;

  165. }

  166.  

  167. BOOL LoadFromFile(LPCTSTR lpSection, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize)

  168. {

  169.     TCHAR ch;

  170.     bool search = true;

  171.     bool find = false;

  172.     int state = 0;

  173.     int idx = 0;

  174.  

  175.     // Get INI filename

  176.     TCHAR lpFileName[MAX_PATH] = {0};

  177.     if(!GetIniFilename(lpFileName, MAX_PATH)) return FALSE;

  178.  

  179.     // Open file

  180.     FILE* fp = _tfopen(lpFileName, _T("rt"));

  181.  

  182.     if (fp == NULL)

  183.         search = false;

  184.  

  185.     while (search && 1 == _ftscanf(fp, _T("%c"), &ch))

  186.     {

  187.         switch (state)

  188.         {

  189.         case 0:    // 첫글자

  190.             if (ch == _T(';'))

  191.                 state = 10;    // 주석 넘기기

  192.             else if (ch == _T('['))

  193.             {

  194.                 idx = 0;

  195.                 lpReturnedString[0] = 0;

  196.                 state = 20;    // AppName 비교

  197.             }

  198.             break;

  199.  

  200.         case 10:

  201.             if (ch == _T('\n'))

  202.                 state = 0;

  203.             break;

  204.  

  205.         case 20:

  206.             if (ch == _T(']'))

  207.             {

  208.                 lpReturnedString[idx++] = 0;

  209.                 if (_tcscmp(lpReturnedString, lpSection) == 0)

  210.                 {

  211.                     idx = 0;

  212.                     lpReturnedString[0] = 0;

  213.                     state = 30;

  214.                 }

  215.                 else

  216.                     state = 10;

  217.             }

  218.             else

  219.                 lpReturnedString[idx++] = ch;

  220.             break;

  221.  

  222.         case 30:

  223.             if (ch == _T('\n'))

  224.                 state = 31;

  225.             break;

  226.         case 31:

  227.             if (ch == _T('['))

  228.                 search = false;

  229.             else if (ch == _T(';'))

  230.                 state = 30;

  231.             else

  232.             {

  233.                 idx = 0;

  234.                 lpReturnedString[idx++] = ch;

  235.                 state = 32;

  236.             }

  237.             break;

  238.         case 32:

  239.             if (ch == _T('='))

  240.             {

  241.                 lpReturnedString[idx++] = 0;

  242.                 if (_tcscmp(lpReturnedString, lpKeyName) == 0)

  243.                 {

  244.                     idx = 0;

  245.                     lpReturnedString[0] = 0;

  246.                     state = 40;

  247.                 }

  248.                 else

  249.                     state = 30;

  250.             }

  251.             else

  252.                 lpReturnedString[idx++] = ch;

  253.             break;

  254.  

  255.         case 40:

  256.             if (ch == _T('\n'))

  257.             {

  258.                 lpReturnedString[idx++] = 0;

  259.                 search = false;

  260.                 find = true;

  261.             }

  262.             else

  263.                 lpReturnedString[idx++] = ch;

  264.             break;

  265.         }

  266.     }

  267.  

  268.     if (!find)

  269.         _tcscpy(lpReturnedString, lpDefault);

  270.  

  271.     if (fp != NULL)

  272.         fclose(fp);

  273.  

  274.     return _tcslen(lpReturnedString);

  275. }

 

 

Back