.ini-parser

Übersicht Sonstiges Smalltalk

Neue Antwort erstellen

 

Sterbendes Lüftlein

Betreff: .ini-parser

BeitragMi, Sep 15, 2010 22:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Text entfernt
 

n-Halbleiter

BeitragMi, Sep 15, 2010 22:53
Antworten mit Zitat
Benutzer-Profile anzeigen
1.: Wikipedia - Der Vorteil: Sieh' dir den Aufbau an. Was kann da nützlich erscheinen? Ansonsten: Im Tutorial unten wird's schön gesagt.

2.: Forensuche ergab z.B. das. Dauerte nur 10 Sekunden, das einzugeben, abzuwarten bis die Ergebnisse da waren und dann schauen (ist, glaube ich, unter den ersten fünf Beiträgen). Suchworte: "ini datei" (:
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit
Ploing!
Blog

"Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935)

Chester

BeitragMi, Sep 15, 2010 23:53
Antworten mit Zitat
Benutzer-Profile anzeigen
[Edit]
1.: Z.B.:
Die Datei lässt sich sehr einfach über den Texteditor bearbeiten und ist somit auch änderbar, wenn man ausversehen über ein Programm irgendwelche Daten reinschreibt, die das Programm zu Absturz bringen.
[/Edit]

Zu 2., ich denke hier lernt man über einen Code am besten:

Hier der INI-Parser, den ich für Gustav's World, geschrieben habe.
Dabei wird eine korrekte Syntax, Kommentare, wahlweiße Groß-/Kleinschreibung berücksichtigt. Entspricht wahrscheinlich aber auch nicht ganz der Wikipedia-Definition, da es eigentlich afaik keine einheitliche Regelungen gibt.

Wenn die Datei geöffnet wird, werden die Kategorien aus der INI-Datei schon gleich mit ihrem jeweiligen Offset in einem Type gespeichert. Dabei wird auch der Startpunkt der nächsten Kategorie gespeichert, damit die Grenzen klar sind. Dann kann man mit einem Befehl eine Kategorie auswählen, wobei hier einfach nur ein "Zeiger" auf den Type gespeichert wird. Und mit dem GetValue Befehl wird dann innerhalb der ausgewählten Kategorie nach dem Eintrag gesucht und geparsed.

BlitzBasic: [AUSKLAPPEN]
Type TINI
Field INIFile
Field path$
End Type

Type TINICategory
Field INIHandle
Field name$
Field pos%
Field nextpos%
End Type

Global INICurrentDirectory.TINICategory

Function INILoad(file$)
Local INI.TINI = New TINI
INI\INIFile = ReadFile(file$)
INI\path = file$
Local C.TINICategory

While (Not Eof(INI\INIFile))
Local CurLine$
Local RightBracketPos%=0

CurLine = Trim(ReadLine(INI\INIFile))
If Left(CurLine,1)="[" Then
RightBracketPos = Instr(CurLine,"]")

If RightBracketPos=0 Then RuntimeError("INI Error in file "+INI\path+": Brackets mismatch on pos: "+FilePos(INI\INIFile)+"!")
If C <> Null Then C\nextpos = FilePos(INI\INIFile)
C = New TINICategory
C\INIHandle = Handle(INI)
C\name$= Trim(Mid(CurLine, 2,RightBracketPos-2))
C\pos=FilePos(INI\INIFile)
EndIf
Wend

If C\nextpos=0 Then C\nextpos=FilePos(INI\INIFile)

Return Handle(INI)
End Function

Function INIClose(INIObj)
Local INI.TINI = Object.TINI(INIObj)
CloseFile INI\INIFile
Delete INI
End Function

Function INISwitchDirectory(INIObj, directory$,case_sensitive=False)
Local INI.TINI = Object.TINI(INIObj)
Local C.TINICategory
For C = Each TINICategory
If C\INIHandle = INIObj Then
If Not case_sensitive Then
If Lower(directory)=Lower(C\name) Then
INICurrentDirectory=C
Return Handle(C)
EndIf
Else
If directory=C\name Then
INICurrentDirectory=C
Return Handle(C)
EndIf
EndIf
EndIf
Next
Debug("INI Error in file "+INI\path+": Category not found!")
End Function

Function INIGetValue$(INIObj,name$,val%=0,case_sensitive=False)
Local INI.TINI = Object.TINI(INIObj)
Local ProbablyCommentary
SeekFile INI\INIFile, INICurrentDirectory\pos

While FilePos(INI\INIFile)<INICurrentDirectory\nextpos
Local CurLine$ = Trim(ReadLine(INI\INIFile))
If Mid(CurLine,1,1)<>"#" And CurLine<> "" And Mid(CurLine,1,1)<>"[" Then ; remember commentaries
Local EqualSign = Instr(CurLine,"=")

If EqualSign > 1 Then
If case_sensitive Then
If Trim(Left(CurLine, EqualSign-1))=name$ Then
ProbablyCommentary=Instr(CurLine,"#",EqualSign)
If ProbablyCommentary=0 Then ProbablyCommentary=-1

Return Trim(Mid(CurLine, EqualSign+1,ProbablyCommentary-EqualSign-1))
EndIf
Else
If Lower(Trim(Left(CurLine, EqualSign-1)))=Lower(name$) Then
ProbablyCommentary=Instr(CurLine,"#",EqualSign)
If ProbablyCommentary=0 Then ProbablyCommentary=-1

Return Trim(Mid(CurLine, EqualSign+1,ProbablyCommentary-EqualSign-1))
EndIf
EndIf
Else
RuntimeError("INI Error in file "+INI\path+": Mismatched Syntax "+FilePos(INI\INIFile)+"!")
EndIf
EndIf
Wend

End Function


Wenn ich bei Gelegenheit noch das Gegenstück zum speichern schreibe, werde ich die Funktionen in das Code-Archive stellen, damit mal eine funktionsfähige Lib drin ist. Bei den bereits vorhanden, fehlt meistens irgendetwas oder wird nicht berücksichtigt.

Firstdeathmaker

BeitragDo, Sep 16, 2010 10:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ein Ini-Parser hat einfach den Vorteil, dass du deinem Programm eine Options.ini beilegen kannst, die jeder Depp mit einem Texteditor öffnen und manipulieren kann, ohne dass er den Quellcode haben muss.

Beispiel:

Du programmierst ein Spiel mit einer Variablen Auflösung und 3 Schwierigkeitsgraden. Die Auflösung liest du aus der ini-Datei, sodass der Spieler bei bedarf die Auflösung jederzeit außerhalb des Programs ändern kann. Das ist vor allem dann praktisch, wenn man im Spiel ausversehen eine zu hohe Auflösung ausgewählt hat, und der Bildschirm daraufhin schwarz bleibt bzw. das Program abstürzt.

Bei meinem Spiel Razoon gibt es z.B. auch so eine Optionsdatei, die allerdings am Anfang durch ein kleines Startprogram bequem mit Werten gefüllt werden kann.


Und das Prinzip ist eigentlich ganz einfach: Entweder du nimmst gleich nen XML Parser, oder aber du denkst dir selbst eine einfache Syntax aus und setzt diese um. Ein Beispiel:

Du legst fest, dass die Variablen immer links, dann ein = Zeichen und dann der Wert kommen soll. Eine Datei sähe dann so aus:

GFX_X=800
GFX_Y=600
FULLSCREEN=1

Beim einlesen liest du immer eine Zeile ein, suchst nach dem ersten = Zeichen, und schneidest links und rechts davon aus. In BMax könnte man diese Wertepaare in einem Wörterbuch (TMap) speichern. Bei BB könnte man ein Type mit zwei Fields (name, value) erstellen. Dann bastelt man noch eine Funktion, welche den Namen erhält und den Wert zurück liefert: GetIniValue$(name$)

Wenn du dann das Program startest, liest du erst die Ini ein, und setzt dann z.B. die Bildschirmauflösungsvariablen auf die Ini-Werte:


Global GFX_X:int = int(GetIniValue("GFX_X"))
Global GFX_Y:int = int(GetIniValue("GFX_Y"))
graphics GFX_X,GFX_Y
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

kriD

BeitragSa, Sep 18, 2010 12:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Genauso (wie FDM es beschrieben hat) entsteht schöner Code!
Das ist die Methode, mit der du (wie ich es dir schonmal in einem Worklogkommentar gesagt habe) nur Einsen und Nullen und sonst keine anderen Zahlen im Code erhälst.

Im grunde kannst du die Dateinen, in dem du deine Werte speicherst nennen wie du willst. .tot .asd .xxx usw.
Wie du willst.
.ini bringt bloß den Vorteil mit sich, dass jeder weiß, was die Datei macht und was er damit machen kann.

Du bist auf einem guten weg, Totensturm. Bald wirst du über deine alten Codes lachen können Wink

lg kriD
Wenn ich du wäre, wäre ich lieber ich!

Firstdeathmaker

BeitragMo, Sep 20, 2010 11:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn du es noch cooler/eleganter haben möchtest, dann schau dir einfach XML an. Es gibt z.B. für BMax ein XML Modul (im englischen Forum, von Bruce), das liest dir XML Dateien ein, und du kannst darüber sehr elegant Objekte/Ini-Dateien lesen. Dazu gibt es noch die möglichkeit, diese auch auf Fehler zu überprüfen. Sehr praktisch und elegant. XML Dateien kann man auch sehr gut mit einem beliebigen Texteditor bearbeiten.
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Smily

BeitragMo, Sep 20, 2010 12:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, XML ist auch nicht gerade DAS wundermittel der informatik Wink

Kommt halt darauf an, was man will.
Für ne relativ kleine Anwendung, in der man nur ein paar simple config-werte wie auflösung, sprache usw haben möchte, sind ini-dateien (also normale variable=wert-auflistungen) wesentlich besser.

Grüße,
Smily
Lesestoff:
gegen Softwarepatente | Netzzensur | brain.exe | Unabhängigkeitserklärung des Internets

"Wir müssen die Rechte der Andersdenkenden selbst dann beachten, wenn sie Idioten oder schädlich sind. Wir müssen aufpassen. Wachsamkeit ist der Preis der Freiheit --- Keine Zensur!"
stummi.org

Firstdeathmaker

BeitragMo, Sep 20, 2010 14:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Was nennst du relativ klein? Klar, wenn man ein 1-Datei Projekt mit weniger als 2000 LOC hat, dann wäre das vllt überdimensioniert. Und nur um 5-10 Werte einzulesen auch. Aber wenn man es sowieso schon für Leveldateien oder Spielstände benutzt?

Aber meiner Meinung nach hat das weniger mit "klein" sondern mit Qualität zu tun. Man kann z.B. über die dts (Schema-Definitionsdatei) prima debugging von ini-Dateien betreiben, falls der User da dran rumgefrickelt hat (sie "kaputtgefrickelt" hat). Das ist z.B. schon Teil der meisten XML-Parsern und muss nicht extra implementiert werden.

Und zum speichern/laden von Spielständen sind sie auch sehr gut geeignet. Im Gegensatz zum reinen Binary-Format kann man diese nämlich auch besser debuggen. Und wenn man wirklich grosse Dateimengen hat, kann man diese ja immer noch binär innerhalb der XML-Datei unterbringen.
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Neue Antwort erstellen


Übersicht Sonstiges Smalltalk

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group