C ++를 사용하여 INI 파일을 구문 분석하려고합니다. 이를 달성하는 가장 좋은 방법은 무엇입니까? INI 파일 처리 (완전히 익숙하지 않은), 오픈 소스 솔루션에 Windows API 도구를 사용해야합니까? 아니면 수동으로 구문 분석을 시도해야합니까?
C ++를 사용하여 INI 파일을 구문 분석하려고합니다. 이를 달성하는 가장 좋은 방법은 무엇입니까? INI 파일 처리 (완전히 익숙하지 않은), 오픈 소스 솔루션에 Windows API 도구를 사용해야합니까? 아니면 수동으로 구문 분석을 시도해야합니까?
답변:
GetPrivateProfileString () 및 GetPrivateProfileInt () 와 같은 Windows API 함수를 사용할 수 있습니다 .
크로스 플랫폼 솔루션이 필요한 경우 Boost의 프로그램 옵션 라이브러리를 사용해보십시오 .
ini 파일을 구문 분석 한 적이 없으므로이 문제에 대해 너무 구체적으로 말할 수 없습니다.
하지만 한 가지 조언이 있습니다. 기존 제품이 요구 사항을 충족하는 한 바퀴를 재발 명하지 마십시오 .
http://en.wikipedia.org/wiki/INI_file#Accessing_INI_files
http://sdl-cfg.sourceforge.net/
http://sourceforge.net/projects/libini/
http://www.codeproject.com/KB /files/config-file-parser.aspx
행운을 빕니다 :)
이미 Qt를 사용하고있는 경우
QSettings my_settings("filename.ini", QSettings::IniFormat);
그런 다음 값을 읽습니다.
my_settings.value("GroupName/ValueName", <<DEFAULT_VAL>>).toInt()
INI 값을 표준 유형과 Qt 유형으로 변환하는 다른 변환기가 많이 있습니다. 자세한 내용은 QSettings에 대한 Qt 설명서를 참조하십시오.
sync()
합니다. 놀라 울 수 있음) 이전에 변수가 정의 된 주석과 순서를 파괴합니다 ...
이 질문은 조금 오래되었지만 내 답변을 게시하겠습니다. 다양한 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);
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";
아마도 늦게 대답 할 수도 있습니다 ..하지만 옵션을 알아볼 가치가 있습니다 .. 크로스 플랫폼 솔루션이 필요하다면 확실히 흥미로운 GLIB를 사용해 볼 수 있습니다 .. ( https://developer.gnome.org/glib/stable/glib- 키-값-파일 -parser.html )
나는이 질문이 매우 오래되었다는 것을 알고 있지만 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
}
이 스레드에서 언급되지 않은 inipp을 사용하게되었습니다.
https://github.com/mcmtroffaes/inipp
MIT 라이센스 헤더 전용 구현으로 프로젝트에 추가 할 수있을만큼 간단하고 사용할 4 줄이었습니다.