سؤال

أنا أحاول تحليل ملف 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 خطوط للاستخدام.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top