[gelöst] Ini-Datei auslesen OHNE API
-
Tach zusammen...
Als blutiger Nichtkönner habe ich hier mal eine Frage an euch.
Ich habe eine INI-Datei mit folgendem Inhalt:
[GoPal] GPVers=5.5
if ( _wfopen( GPWini, L"r") !=0) { ini = _wfopen( GPWini, L"r" ); while(fgetws(cText, 2000, ini) != 0) { wcscpy(variable1, cText); if (wcscmp(variable1, L"[GoPal]\n\n") == 0 || wcscmp(variable1, L"[GoPal]\n") == 0 ) . . .
Bisher war es ausreichend, die darin enthaltenen Einträge über:
if (wcscmp(variable1, L"GPVers=5.5") == 0 || wcscmp(variable1, L"GPVers=5.5\n") == 0 || wcscmp(variable1, L"GPVers=5.5\n\n") == 0 && iniflag == TRUE)
miteinander zu vergleichen, da dort keine anderen Werte stehen konnten.
Jetzt habe ich das Problem, dass dort in einer anderen Abteilung unterschiedliche Werte drin stehen können, die ich für die weitere Verarbeitung auslesen müsste.Wie würdet Ihr das ohne API machen? Das Ganze muss nämlich auf Windows CE5 lauffähig sein
-
"[GoPal]" Suchen. An dem Punkt weiter nach "GPVers=" suchen, atof(p + strlen("GPVers=")).
Hoffe ich habe die Frage richtig verstanden..
-
hmmm...
das würde aber bedeuten, dass dort immer eine Zahl hinterlegt wäre.
Nur leider könnte das auch eine Buchstaben-Zahl-Kombination sein.Also.... Ich lese die komplette INI in Variable1 ein, suche erst nach [GoPal] dann nach GPVers=, so weit klar. das mach ich bisher ja auch, nur dass ich diesen String dann verglichen habe mit dem was ich vorher fest definiere.
Ich krieg nur keinen Kopf dran, wie ich die eingelesene Zeile im String teile nach dem Gleichheitszeichen...
Das, was ich dort erhalte wird dann über wcscat(variable, wert \n"); einem String hinzugefügt, der für weitere Zwecke in eine Textdatei geschrieben wird....
Vielleicht steh ich gerade nur zu nah am Wald, dass ich die Bäume nicht mehr sehe?
-
int main(int argc, char *argv[]) { char toSplit[] = "Hallo=asd=123"; char first[100] = {0}; char last[100] = {0}; int position = 0; char* found = NULL; found = strrchr( toSplit, '=' ); if(found != NULL) { position = found - toSplit + 1; strncat(first,toSplit,position - 1); strncat(last,toSplit+position,strlen(toSplit)-position); } printf("First: %s\nLast: %s\n", first, last); return 0; }
Müsste so funktionieren
-
Bist du dir wirklich sicher, dass du die von der WinAPI bereitgestellte Funktion GetProfileString, die genau das macht, was du erreichen willst, nicht verwenden willst und stattdessen lieber selbst rumbasteln?
-
he wutzi wir sind hier im _ansi c_ subforum... das kennt leider keine winapi
-
Wutz schrieb:
Bist du dir wirklich sicher, dass du die von der WinAPI bereitgestellte Funktion GetProfileString, die genau das macht, was du erreichen willst, nicht verwenden willst und stattdessen lieber selbst rumbasteln?
Wenn das gehen würde, hätte ich die mir bereits bekannte Funktion GetProfilString() sehr gerne benutzt, weil ich am liebsten mit der WinAPI arbeite...
Den Ansatz hab ich ja schon dank Gast1337.
Ich geh da morgen noch mla frisch dran und denke, dass ich das jetzt hin bekommen sollte.
Wenn nicht, habt ihr mich wieder am Hacken...
-
Ja, neue Applikationen sollen laut Microsoft die Registry nutzen. Das ist wahrscheinlich der Grund, weshalb GetPrivateProfileString nicht von CE unterstützt wird.
Im Grunde genommen ist es aber recht einfach, sich diese Funktion selber zu schreiben.// Diese Funktionen im Header deklarieren char* GetIniBuffer(const char* Filename); void FreeIniBuffer(char** Buffer); int GetIniString(const char* AppName, const char* KeyName, char* ReturnedString, DWORD Size, const char* Buffer); const char* FindNext(const char* buffer, char c, char fail) { while(*buffer) { if(*buffer == c) { return buffer; } if(*buffer == fail) return NULL; ++buffer; } return NULL; } const char* GetNextIniSection(const char* AppName, const char* Index) { const char* Buffer = Index; while(*Buffer) { if(*Buffer=='[') { Index = ++Buffer; return Index; } ++Buffer; } return NULL; } const char* GetIniSection(const char* AppName, const char* Buffer) { const size_t len = strlen(AppName); const char* Index; while(Index = GetNextIniSection(AppName,Buffer)) { if(strnicmp(Index, AppName, len)==0) { Index+=len; while(*Index++ && *Index!=']' && isspace(*Index)); return Index; } Buffer=Index; } return NULL; } const char* GetIniKey(const char* KeyName, const char* Buffer) { const size_t len = strlen(KeyName); const char* beg = Buffer; while(*beg) { if(strnicmp(beg, KeyName, len)==0) { beg = FindNext(beg,'=','['); if(beg) { return ++beg; } return NULL; } ++beg; } return NULL; } int GetIniString(const char* AppName, const char* KeyName, char* ReturnedString, DWORD Size, const char* Buffer) { if(!AppName) return ReadIniSections(Buffer, ReturnedString, Size); // müsste ggf. noch geschrieben werden const char* Index = GetIniSection(AppName,Buffer); if(Index) { Index = GetIniKey(KeyName, Index); if(Index) { size_t si = 0; while(*Index && *Index!='\n' && si<(Size-1)) { *ReturnedString++ = *Index++; ++si; } *ReturnedString=0; return 1; } } return 0; } char* GetIniBuffer(const char* Filename) { HANDLE file = CreateFile(Filename,GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(file == INVALID_HANDLE_VALUE) { SetLastError(ERROR_FILE_NOT_FOUND); return NULL; } DWORD fsHigh; DWORD fs = GetFileSize(file, &fsHigh); if(fsHigh) { // ??? SetLastError(ERROR_FILE_CORRUPT); return NULL; } char* Buffer = (char*)malloc(fs); if(!Buffer) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); CloseHandle(file); return NULL; } if(!ReadFile(file, Buffer, fs, &fs, NULL)) { SetLastError(ERROR_FILE_CORRUPT); free(Buffer); CloseHandle(file); return NULL; } CloseHandle(file); return Buffer; } void FreeIniBuffer(char** Buffer) { free(*Buffer); *Buffer = 0; } int main() { char* Buffer = GetIniBuffer("ini.ini"); if(Buffer) { char c[80]; if(GetIniString("section","key",c,80,Buffer)) { printf("%s\n",c); } FreeIniBuffer(&Buffer); } else { puts("file not found"); } return 0; }
Ratsam ist also, die Funktionen so zu schreiben, als hätten sie selber kaum etwas zu tun - die wirkliche Arbeit wird auf andere Funktionen ausgelagert, von denen man widerum denkt, sie hätten kaum etwas zu tun...
Es ist so gut wie gar nicht getestet, nicht dokumentiert und die Funktion ReadIniSections müsste noch implementiert werden (was aber normalerweise
ReadIniInt und ReadIniFloat könnten mit Hilfe von ReadIniString sehr leicht hinzugefügt werden.nicht nötig ist).PS: Der Bequemlichkeit halber ist alles C99-konform geschrieben.
-
Ohoh, der Cast des Returnwerts von malloc sollte eigentlich nicht da sein
, ein CloseHandle fehlt auch noch
.
-
Moin zusammen,
stimmt, man möchte die REG nutzen, deshalb hat man GetProfilString() nicht implementiert... Nur mit dem Nachteil, dass nach einem Hardreset bei den meisten PDA/PNA dann die REG wieder auf Auslieferzustand ist, Änderungen durch mich also verschwunden sind.
Gut, man könnte Startsequenzen dazwischen bauen, die diese Einträge wieder setzt, aber das ist mir zu doof und bremst den Systemstart aus. Deshalb der Weg über die INI.
...diese Funktion komplett selber schreiben... Sorry, da muss ich kneifen, da ich nur blutiger Nichtkönner bin...
-
Moin, moin,
'nen ini- Reader hab' ich, würd' ich Dir auch geben.
Ist an einem Vormittag entstanden, als das von Sourceforge geholte Exemplar einer Lib mit SegFaults, hinter die ich nie gekommen bin, 'ne ganze DLL lahmgelegt hat.
Kann inis nur lesen, ist nicht schnell (Directory ohne Hash, durchsucht stringmäßig), funktioniert aber ohne Abkacken und Memory Leaks.Ini- basiert mach' ich, weil ohne OS keine zentralen Instanzen vorhanden sind, das ist bei mir der Normalfall.
Bißchen viel zum Posten hier, bitt ggf. per PM anfordern.
-
Das Auslesen einer INI ist nun wirklich nicht die große Kunst. Das packst du locker.
Edit: ich habs aus den gleichen Gründen wie PointerCrash mal gemacht. Sowas brauch man immer früher oder später mal, wenn man Applikationen in unterschiedlichen Konfigurationen einsetzen will.
-
It0101 schrieb:
Edit: ich habs aus den gleichen Gründen wie PointerCrash mal gemacht. Sowas brauch man immer früher oder später mal, wenn man Applikationen in unterschiedlichen Konfigurationen einsetzen will.
Hast Du Deinen mit Hash und rewrite oder auch nur "Fauler Hund-" IniReader, so wie ich?
-
int getPrivateProfileString( const char* sektion, const char* name, const char* vorgabe, char *wert, int max, const char* datei) { char zeile[100],t1[100],t2[100],s[100]=""; FILE *f = fopen(datei,"r"); if( !f ) return -1; while( fgets(zeile,100,f) ) if( 2==sscanf(zeile,"%[^\]]%[^\n]",t1,t2) && !strcmp((sscanf(t2,"%s",zeile),zeile),"]") && ((sscanf(t1,"%s",zeile),zeile),*zeile=='[') ) strcpy(s,(sscanf(strchr(t1,'[')+1,"%s",zeile),zeile)); else if( !strcmp(s,sektion) ) if( 2==sscanf(zeile,"%[^=]=%[^\n]",t1,t2) && !strcmp((sscanf(t1,"%s",zeile),zeile),name) ) return fclose(f),t2[max-1]=0,strlen(strcpy(wert,t2))+1; fclose(f); return strlen(strcpy(wert,vorgabe))+1; }
Funktioniert für einfache Beispiele
[bla] fasel=123
wie auch für kompliziertere
[ bla ] fasel = 1 2 3
-
Ihr macht mich ganz jeck im Kopf...
Dabei brauche ich nur ein paar Einträge aus der INI, die sowieso nur knapp 20 Einträge hat, wenn es hoch kommt...Das Ganze dient einem Tool, mit dem wir den User entlasten wollen... Damit werden aus der REG und der von uns generierten INI bestimmte Werte ausgelesen und einem Tool zur Verfügung gestellt, wo der User die Möglichkeit hat einen Screenshot zu erstellen.
Wir haben halt immer wieder das Problem, dass User ein Problem melden, aber nicht in der Lage sind, das 1. genau zu beschreiben welche Hard- und Software-Kombination sie da haben, noch in der Lage sind nach Anleitung uns diese Informationen zu beschaffen.... DAUs halt...
So weit hab ich das Tool fertig, es fehlt halt "nur" noch das Auslesen dieses einen INI-Eintrages, aber das bekomme ich auch noch gebacken.
Erst mal herzlichen Dank für Eure Hilfe!!!
-
naja, wenn du aus der REG liest bist du ja auf Windows, sprich es würde daher doch nichts gegen GetPrivateProfileString() oder WritePrivateProfileString()
sprechen oder? ich meine wieso dann der Aufwand?
-
Weil CE5 GetPrivateProfileString() und WritePrivateProfileString() nicht unterstützt... das ist ja das doofe!
-
ach ja, steht ja weiter oben... hmm, dann ist der aufwand berechtigt ^^
selber arbeite ich auch grad intensiv mit ini dateien, doch hab ich das Glück
das ganze mit der API zu erledigen =bwobei das von Wutz ziemlich sicher funktionieren wird, zudem ich mir vorstellen kann,
nur schon von der beschreibung her, dass die Funktion ziemlich allgemein bzw.
Optional gehalten wurde sprich du kannst sie verwenden da sie ziemlich sicher
portabel ist.denn wie Wutz geschrieben hatte:
Wutz schrieb:
Funktioniert für einfache Beispiele
[bla] fasel=123
wie auch für kompliziertere
[ bla ] fasel = 1 2 3
-
hmmm... das krieg ich einfach nicht gebacken. Irgendwo hab ich da eine persönliche Einschränkung in meinem Verständnis... oder es liegt an mangelnden Kenntnissen. Das Lösung von @wutz verstehe ich nämlich überhaupt nicht... leider
Könnt Ihr mir hier mal bitte aufs Pferd helfen?
char toSplit[] = "Version"; char first[100] = {0}; char last[100] = {0}; int position = 0; char* found = NULL; if ( _wfopen( GPWini, L"r") !=0) { ini = _wfopen( GPWini, L"r" ); while(fgetws(cText1, 2000, ini) != 0) { wcscpy(variable1, cText1); if (wcscmp(variable1, L"[GoPal]\n\n") == 0 || wcscmp(variable1, L"[GoPal]\n") == 0 ) iniflag == TRUE; { found = strrchr( toSplit, '=' ); if(found != NULL) { position = found - toSplit + 1; strncat(first,toSplit,position - 1); strncat(last,toSplit+position,strlen(toSplit)-position); } } } swprintf(hStr5, L"%d", last); wcscat(variable, hStr5); wcscat(variable, L"\n"); } else wcscat(variable, L"Fehler\n");
Die INI sieht folgendermassen aus:
[GoPal] GPVers=5.5 Version=91940
...und ich brauche lediglich den Eintrag von Version.
GPVers hole ich mir über eine wcscmp()Funktion... nur für wcscmp() sind das zu viele Möglichkeiten, die ich abfangen müsste.
-
Ich kriegs nicht gebacken...
Hab beschlossen, das auszulagern in eine Textdatei. Da brauch ich nur den String einzulesen und fertig...Das ist zwar keine optimale Lösung, aber ich bin zu doof, einen String zu splitten. Vielleicht schaff ich das irgendwann mal...
Danke für eure Hilfeversuche!