ما هي أسهل طريقة تحليل ملف INI في C++?
سؤال
أنا أحاول تحليل ملف INI باستخدام C++.أي نصائح حول ما هي أفضل طريقة لتحقيق ذلك ؟ يجب استخدام API Windows أدوات INI المعالجة (التي أنا غير مألوف تماما) مفتوح المصدر حل أو محاولة تحليل ذلك يدويا ؟
المحلول
يمكنك استخدام وظائف API Windows مثل GetPrivateProfileString() و GetPrivateProfileInt().
نصائح أخرى
إذا كنت بحاجة إلى حل عبر منصة ، في محاولة دفعة خيارات البرنامج المكتبة.
لم يسبق لي تحليل ملفات 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
بالتوفيق :)
يمكنني استخدام SimpleIni.هو عبر منصة.
إذا كنت بالفعل باستخدام Qt
QSettings my_settings("filename.ini", QSettings::IniFormat);
ثم قراءة قيمة
my_settings.value("GroupName/ValueName", <<DEFAULT_VAL>>).toInt()
هناك مجموعة أخرى من محول تحويل INI القيم في كل من الأنواع القياسية و Qt أنواع.انظر Qt الوثائق على QSettings للحصول على مزيد من المعلومات.
هذا السؤال هو قديم ولكن أنا جوابي.لقد اختبرت مختلف INI الطبقات (يمكنك ان ترى لهم على الموقع) و أود أيضا أن استخدام simpleIni لأنني أريد العمل مع ملفات INI على كل من ويندوز و جفل.نافذة GetPrivateProfileString() يعمل فقط مع التسجيل على جفل.
فمن السهل جدا أن تقرأ مع simpleIni.هنا مثال:
#include "SimpleIni\SimpleIni.h"
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile(FileName);
const char * pVal = ini.GetValue(section, entry, DefaultStr);
inih هو بسيط ini محلل مكتوب في C, لأنه يأتي مع 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";
صاحب البلاغ أيضا قائمة من المكتبات الموجودة هنا.
هل حاولت libconfig;جدا JSON-مثل بناء الجملة.أنا يفضل هو على XML ملفات التكوين.
إذا كنت مهتما في منصة قابلية ، يمكنك أيضا محاولة دفعة.PropertyTree.وهو يدعم ini كما persistancy شكل, على الرغم من أن الملكية شجرة بلدي 1 المستوى العميق فقط.
إلا إذا كنت تخطط على جعل التطبيق عبر منصة ، باستخدام Windows API المكالمات يمكن أن يكون أفضل وسيلة للذهاب.فقط تجاهل المذكرة في وثائق API عن المقدمة فقط 16-bit app التوافق.
ربما تأخر في الإجابة..ولكن يستحق معرفة الخيارات..إذا كنت بحاجة إلى حل عبر منصة , بالتأكيد يمكنك محاولة سطحي ، ، مثيرة للاهتمام..(https://developer.gnome.org/glib/stable/glib-Key-value-file-parser.html)
أعرف أن هذا السؤال قديم جدا, ولكن أتيت عليه لأنني بحاجة لشيء عبر منصة لينكس ، win32...كتبت وظيفة أدناه ، بل هو وظيفة واحدة التي يمكن تحليل ملفات INI, ونأمل أن الآخرين سوف تجد أنه من المفيد.
قواعد & المحاذير:buf لتحليل يجب أن تكون فارغة إنهاء السلسلة.تحميل ملف ini في مجموعة شار سلسلة استدعاء هذه الدالة إلى تحليل ذلك.القسم أسماء يجب أن يكون [] بين قوسين من حولهم مثل هذا [MySection], أيضا القيم أقسام يجب أن تبدأ على الخط دون أن يؤدي المساحات.فإنه سيتم تحليل الملفات مع ويندوز أو مع لينكس خط النهايات.التعليقات يجب استخدام # أو / و/ تبدأ في الجزء العلوي من الملف, لا توجد تعليقات ينبغي أن تكون مختلطة مع INI إدخال البيانات.ونقلت القراد قلص من طرفي عودة السلسلة.المساحات هي فقط قلص اذا كان خارج الاقتباس.سلاسل ليس مطلوبا أن يكون الاقتباس ، whitespaces هي قلص إذا نقلت في عداد المفقودين.يمكنك أيضا استخراج أرقام أو بيانات أخرى ، على سبيل المثال إذا كان لديك تطفو مجرد إجراء 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
كان معهد ماساتشوستس للتكنولوجيا مرخصة رأس فقط التنفيذ الذي كان بسيطا بما فيه الكفاية لإضافة مشروع و 4 خطوط للاستخدام.