C ++에서 INI 파일을 구문 분석하는 가장 쉬운 방법은 무엇입니까?


89

C ++를 사용하여 INI 파일을 구문 분석하려고합니다. 이를 달성하는 가장 좋은 방법은 무엇입니까? INI 파일 처리 (완전히 익숙하지 않은), 오픈 소스 솔루션에 Windows API 도구를 사용해야합니까? 아니면 수동으로 구문 분석을 시도해야합니까?

답변:


112

GetPrivateProfileString ()GetPrivateProfileInt () 와 같은 Windows API 함수를 사용할 수 있습니다 .


4
GetPrivateProfileInt () 및 기타 함수는 더 이상 사용되지 않고 이전 16 비트 시스템과의 기본 호환성을 위해서만 제공되기 때문에 MSDN에서 권장하지 않습니다. 그 대신 다른 접근 방식을 사용하십시오. msdn.microsoft.com/en-us/library/windows/desktop/…
Zdeno Pavlik

MS는 더 이상 ini 파일을 사용하는 것을 원하지 않기 때문에 쓸모가 없습니다. 실제로 그러한 파일을 읽거나 쓰려는 경우 여전히 이상적입니다.
Neil

114

크로스 플랫폼 솔루션이 필요한 경우 Boost의 프로그램 옵션 라이브러리를 사용해보십시오 .


1
나는이 도서관도 제안 할 것이다
varnie

21
이것이 갈 길입니다. 사람들이 왜 그렇게 일반적이지 않은 답변을 찬성하는 지 이해가 안갑니다.
Ramadheer Singh

17
@Gollum, Windows가 주어진 종속성 인 것처럼 들립니다. 프로그램 옵션 라이브러리를 사용한다는 것은 다른 종속성을 취하는 것을 의미합니다. 때로는 그것은 큰 문제가 아니고 때로는 그렇습니다.
IJ Kennedy

5
@malat 혼란 스럽습니다. 반대 투표에 대해 언급하지 않았습니까?
sjdowling

2
그는 기존 INI 파일을 읽으려고합니다. INI와 유사한 형식을 사용하고 있기 때문에 boost를 사용하는 것은 답이 아닙니다.
Lothar 2015


16

이미 Qt를 사용하고있는 경우

QSettings my_settings("filename.ini", QSettings::IniFormat);

그런 다음 값을 읽습니다.

my_settings.value("GroupName/ValueName", <<DEFAULT_VAL>>).toInt()

INI 값을 표준 유형과 Qt 유형으로 변환하는 다른 변환기가 많이 있습니다. 자세한 내용은 QSettings에 대한 Qt 설명서를 참조하십시오.


나쁘지는 않지만 변경하면 실제로 알리지 않고 .ini 파일에 다시 저장하고 (즉, 소멸자가를 호출 sync()합니다. 놀라 울 수 있음) 이전에 변수가 정의 된 주석과 순서를 파괴합니다 ...
알렉시스 WILKE


8

이 질문은 조금 오래되었지만 내 답변을 게시하겠습니다. 다양한 INI 클래스를 테스트했습니다 (제 웹 사이트 에서 볼 수 있습니다. 했으며, Windows와 winCE 모두에서 INI 파일로 작업하기를 원하기 때문에 simpleIni도 사용합니다. Window의 GetPrivateProfileString ()은 winCE의 레지스트리에서만 작동합니다.

simpleIni로 읽기가 매우 쉽습니다. 예를 들면 다음과 같습니다.

#include "SimpleIni\SimpleIni.h"    
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile(FileName);
const char * pVal = ini.GetValue(section, entry, DefaultStr);

6

inih 는 C로 작성된 간단한 ini 파서이며 C ++ 래퍼도 함께 제공됩니다. 사용 예 :

#include "INIReader.h"    

INIReader reader("test.ini");

std::cout << "version="
          << reader.GetInteger("protocol", "version", -1) << ", name="
          << reader.Get("user", "name", "UNKNOWN") << ", active="
          << reader.GetBoolean("user", "active", true) << "\n";

저자는 또한 여기 에 기존 라이브러리 목록이 있습니다 .



3

플랫폼 이식성에 관심이있는 경우 Boost.PropertyTree를 사용해 볼 수도 있습니다. 속성 트리는 1 레벨 깊이이지만 ini를 지속성 형식으로 지원합니다.


2

앱을 크로스 플랫폼으로 만들 계획이 없다면 Windows API 호출을 사용하는 것이 가장 좋은 방법입니다. 16 비트 앱 호환성을 위해서만 제공된다는 API 문서의 참고 사항을 무시하십시오.



0

나는이 질문이 매우 오래되었다는 것을 알고 있지만 Linux, win32 용 크로스 플랫폼이 필요했기 때문에 발생했습니다. 아래 함수를 작성했습니다. INI 파일을 구문 분석 할 수있는 단일 함수이므로 다른 사람들이 유용하다고 생각합니다.

규칙 및주의 사항 : 구문 분석 할 buf는 NULL로 끝나는 문자열이어야합니다. ini 파일을 char 배열 문자열로로드하고이 함수를 호출하여 구문 분석하십시오. 섹션 이름에는이 [MySection]과 같이 [] 대괄호가 있어야하며 값과 섹션은 선행 공백없이 행에서 시작해야합니다. Windows \ r \ n 또는 Linux \ n 줄 끝으로 파일을 구문 분석합니다. 주석은 # 또는 //를 사용하고 파일 맨 위에서 시작해야하며 주석은 INI 항목 데이터와 혼합되어서는 안됩니다. 따옴표와 눈금은 반환 문자열의 양쪽 끝에서 잘립니다. 공백은 따옴표 밖에있는 경우에만 잘립니다. 문자열에는 따옴표가 필요하지 않으며 따옴표가 없으면 공백이 잘립니다. 숫자 나 다른 데이터를 추출 할 수도 있습니다. 예를 들어 float가있는 경우 ret 버퍼에서 atof (ret)를 수행합니다.

//  -----note: no escape is nessesary for inner quotes or ticks-----
//  -----------------------------example----------------------------
//  [Entry2]
//  Alignment   = 1
//  LightLvl=128
//  Library     = 5555
//  StrValA =  Inner "quoted" or 'quoted' strings are ok to use
//  StrValB =  "This a "quoted" or 'quoted' String Value"
//  StrValC =  'This a "tick" or 'tick' String Value'
//  StrValD =  "Missing quote at end will still work
//  StrValE =  This is another "quote" example
//  StrValF =  "  Spaces inside the quote are preserved "
//  StrValG =  This works too and spaces are trimmed away
//  StrValH =
//  ----------------------------------------------------------------
//12oClocker super lean and mean INI file parser (with section support)
//set section to 0 to disable section support
//returns TRUE if we were able to extract a string into ret value
//NextSection is a char* pointer, will be set to zero if no next section is found
//will be set to pointer of next section if it was found.
//use it like this... char* NextSection = 0;  GrabIniValue(X,X,X,X,X,&NextSection);
//buf is data to parse, ret is the user supplied return buffer
BOOL GrabIniValue(char* buf, const char* section, const char* valname, char* ret, int retbuflen, char** NextSection)
{
    if(!buf){*ret=0; return FALSE;}

    char* s = buf; //search starts at "s" pointer
    char* e = 0;   //end of section pointer

    //find section
    if(section)
    {
        int L = strlen(section);
        SearchAgain1:
        s = strstr(s,section); if(!s){*ret=0; return FALSE;}    //find section
        if(s > buf && (*(s-1))!='\n'){s+=L; goto SearchAgain1;} //section must be at begining of a line!
        s+=L;                                                   //found section, skip past section name
        while(*s!='\n'){s++;} s++;                              //spin until next line, s is now begining of section data
        e = strstr(s,"\n[");                                    //find begining of next section or end of file
        if(e){*e=0;}                                            //if we found begining of next section, null the \n so we don't search past section
        if(NextSection)                                         //user passed in a NextSection pointer
        { if(e){*NextSection=(e+1);}else{*NextSection=0;} }     //set pointer to next section
    }

    //restore char at end of section, ret=empty_string, return FALSE
    #define RESTORE_E     if(e){*e='\n';}
    #define SAFE_RETURN   RESTORE_E;  (*ret)=0;  return FALSE

    //find valname
    int L = strlen(valname);
    SearchAgain2:
    s = strstr(s,valname); if(!s){SAFE_RETURN;}             //find valname
    if(s > buf && (*(s-1))!='\n'){s+=L; goto SearchAgain2;} //valname must be at begining of a line!
    s+=L;                                                   //found valname match, skip past it
    while(*s==' ' || *s == '\t'){s++;}                      //skip spaces and tabs
    if(!(*s)){SAFE_RETURN;}                                 //if NULL encounted do safe return
    if(*s != '='){goto SearchAgain2;}                       //no equal sign found after valname, search again
    s++;                                                    //skip past the equal sign
    while(*s==' '  || *s=='\t'){s++;}                       //skip spaces and tabs
    while(*s=='\"' || *s=='\''){s++;}                       //skip past quotes and ticks
    if(!(*s)){SAFE_RETURN;}                                 //if NULL encounted do safe return
    char* E = s;                                            //s is now the begining of the valname data
    while(*E!='\r' && *E!='\n' && *E!=0){E++;} E--;         //find end of line or end of string, then backup 1 char
    while(E > s && (*E==' ' || *E=='\t')){E--;}             //move backwards past spaces and tabs
    while(E > s && (*E=='\"' || *E=='\'')){E--;}            //move backwards past quotes and ticks
    L = E-s+1;                                              //length of string to extract NOT including NULL
    if(L<1 || L+1 > retbuflen){SAFE_RETURN;}                //empty string or buffer size too small
    strncpy(ret,s,L);                                       //copy the string
    ret[L]=0;                                               //null last char on return buffer
    RESTORE_E;
    return TRUE;

    #undef RESTORE_E
    #undef SAFE_RETURN
}

사용 방법 ... 예 ....

char sFileData[] = "[MySection]\r\n"
"MyValue1 = 123\r\n"
"MyValue2 = 456\r\n"
"MyValue3 = 789\r\n"
"\r\n"
"[MySection]\r\n"
"MyValue1 = Hello1\r\n"
"MyValue2 = Hello2\r\n"
"MyValue3 = Hello3\r\n"
"\r\n";
char str[256];
char* sSec = sFileData;
char secName[] = "[MySection]"; //we support sections with same name
while(sSec)//while we have a valid sNextSec
{
    //print values of the sections
    char* next=0;//in case we dont have any sucessful grabs
    if(GrabIniValue(sSec,secName,"MyValue1",str,sizeof(str),&next)) { printf("MyValue1 = [%s]\n",str); }
    if(GrabIniValue(sSec,secName,"MyValue2",str,sizeof(str),0))     { printf("MyValue2 = [%s]\n",str); }
    if(GrabIniValue(sSec,secName,"MyValue3",str,sizeof(str),0))     { printf("MyValue3 = [%s]\n",str); }
    printf("\n");
    sSec = next; //parse next section, next will be null if no more sections to parse
}

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.