Entwickler-Ecke

Dateizugriff - Ini mit Konsolenanwendung auslesen/schreiben


Mister Riös - So 13.09.09 11:15
Titel: Ini mit Konsolenanwendung auslesen/schreiben
Hi,
ich suche eine Möglichkeit mit Delphi (7) in eine vorhandene INI-Datei zu schreiben und diese auzulesen. Ich würde das Ganze gerne mit möglichst wenig Aufwand programmieren. Dummerweise ist es mit meinen Kenntnissen nicht sehr weit her, weswegen ich mit vielen gefundenen Antworten nichts anfangen kann. Aus diesem Grund wäre ich über einige Eklärungen sehr froh =).

Danke schonmal im Vorraus!


Narses - So 13.09.09 11:26

Moin und :welcome: im Delphi-Forum!

Der Zugriff auf INI-Dateien klappt problemlos aus einer Konsolenanwendung heraus. Was hast du denn bisher für Versuche unternommen? Wie sieht dein aktueller Code aus? :nixweiss:

cu
Narses


Andreas L. - So 13.09.09 11:37

Als erstes musst du die Unit IniFiles zu deiner Uses-Klausel hinzufügen. Das könnte so aussehen:

Delphi-Quelltext
1:
2:
uses
  SysUtils, ..., IniFiles;


Dann musst du noch ein Ini-Objekt erstellen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var
  ini: TMemIniFile;
begin
  ini := TMemIniFile.Create('C:\Datei.ini');
  try
    //hier mit dem Ini-Objekt arbeiten
  finally
    ini.free;
  end;
end;


Wenn du jetzt Ini. eingibst, sollte sich die Programmierhilfe öffnen. Dort steht welche Methoden (Prozeduren und Funktionen) du verwenden kannst. Wenn deine Ini-Datei z. B. so aufgebaut ist

Quelltext
1:
2:
3:
[Section]
Key1=ValueXYZ
Key2=ValueBlubb


kannst du mit
ReadString('Section''Key1'''); //letzter Parameter ist der Rückgabewert falls die Sektion und/oder Key nicht vorhanden ist
ValueXYZ auslesen. Schreiben geht analog dazu mit
WriteString('Section''Key1''Mein neuer Wert');.
Wenn du Änderungen an der Ini vorgenommen hast musst du unbedingt noch UpdateFile aufrufen um die Änderungen in die Datei zu übertragen. Dies machst du aber nicht bei jedem Schreibzugriff sondern nur wenn du mit der Ini komplett fertig bist.


Mister Riös - So 13.09.09 12:12

Vielen Dank für die schnelle Antwort!
Jetzt funktioniert das Schreiben in die Datei schon. Nur hab ich noch ein Problem mit dem Auslesen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
uses
  SysUtils, inifiles;

var
  INI: TMemIniFile;
  wert: string;

begin
ini := TMemIniFile.Create('I:\Delphi_Projects\Chat\Wert.ini');

try
 //ini.ReadString('Section_1','Wert','');
 ini.WriteString('Section_1','Wert','Test');

finally
ini.UpdateFile;
ini.free;
end;

readln;
end.


So sieht das Ganze jetzt aus. Meine Frage: Ich hab oben zum Test den Teil mit "ReadString" auskommentiert. Jetzt würde ich gern wissen, ob nach dem Auslesen dieser Wert auch irgendwo (Variable) gespeichert wird^^. Also ich hatte oben schonmal eine Variable "Wert" deklariert, die ich dann nach dem Auslesen gerne ausgeben würde... Was muss ich da ändern?

Moderiert von user profile iconNarses: Code- durch Delphi-Tags ersetzt


jaenicke - So 13.09.09 12:22

ReadString gibt dir den Wert zurück.

Delphi-Quelltext
1:
wert := ini.ReadString...                    
Du solltest den Code ordentlich einrücken (und im Forum bitte delphi- statt code-Tags benutzen ;-)), dann sieht man auch besser was passiert.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
uses
  SysUtils, IniFiles;

var
  ini: TMemIniFile;
  wert: string;
begin
  ini := TMemIniFile.Create('I:\Delphi_Projects\Chat\Wert.ini');

  try
    //wert := ini.ReadString('Section_1', 'Wert', '');
    ini.WriteString('Section_1''Wert''Test');

    ini.UpdateFile;
  finally
    ini.Free;
  end;

  ReadLn;
end.
Wichtig ist auch, dass UpdateFile nicht hinter das finally gehört. Im finally soll sichergestellt werden, dass bei einer Exception das Objekt freigegeben wird. Wenn jetzt bei deinem Code aber eine bei UpdateFile auftritt, hast du ein Speicherleck.

// EDIT:
Ach ja: Und statt des absoluten Pfads kannst du auch den der Exe [http://www.delphi-library.de/viewtopic.php?p=499701] nehmen für den Anfang (wie es dann richtig gemacht wird [http://www.delphi-library.de/viewtopic.php?p=548600], ist für kleine Programme nur für dich erst einmal nicht so wichtig).

Delphi-Quelltext
1:
  ini := TMemIniFile.Create(ExtractFilePath(ParamStr(0)) + 'Wert.ini');                    


Mister Riös - So 13.09.09 12:37

Aaah! Wunderbar, jetzt klapp's.
Damit müsste ich alles haben, wenn ich noch Probleme hab frag ich;-)

Ich bin wirklich froh das einem hier so gut geholfen wird!^^


Mister Riös - So 13.09.09 14:27

Hallo nochmal,
leider klappt das Programm jetzt mit einigen Veränderungen immernoch nicht.

Das Programm soll den vom User eingegebenen Wert in der Variable "Wert" speichern. Wenn Der User nichts eingegeben hat (Wert = '') soll das Programm den Inhalt der INI-Datei auslesen (Section_1\Wert), in der Variable "Ausgabe" speichern und ausgeben. Wenn der User etwas eingegeben hat, soll das Programm diese Eingabe (Wert) in den Angegebenen INI-Key schreiben.
Das Ganze soll mit einer Schleife 10 Mal wiederholt werden, dann soll sich das Programm beenden.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
uses
  SysUtils, inifiles;

var
  INI: TMemIniFile;
  wert, Ausgabe: string;
  I:integer;

begin
 ini := TMemIniFile.Create('I:\Delphi_Projects\Chat\Wert.ini');
 for I := 0 to 10 do
 begin
  try
   readln(Wert);
   if Wert = '' then
   begin
    Ausgabe := ini.ReadString('Section_1','Wert','Fehler');
    writeln(Ausgabe);
   end
   else
   begin
    ini.WriteString('Section_1','Wert',Wert);
    ini.UpdateFile;
   end;

  finally
   ini.free;
  end;

 end;
 readln;
end.


Die INI dazu:

Quelltext
1:
2:
[Section_1]
Wert=Test


Wenn ich das Programm so ausführe sagt mir der Debugger unten:
Zitat:
[Fataler Fehler] Ausgabedatei 'I:\Chat\Chat.exe' kann nicht erstellt werden



Was ist falsch?


jaenicke - So 13.09.09 14:39

Das sagt nicht der Debugger sondern der Compiler und das heißt ganz einfach, dass das Programm noch läuft (oder in das Ausgabeverzeichnis nicht geschrieben werden kann).

// EDIT:
Moment mal, der Pfad in deinem Programm und die Meldung des Compilers stimmen ja gar nicht überein? :gruebel:


Mister Riös - So 13.09.09 15:45

Oh mann, du hast natürlich Recht! Man kann schon dumm sein oO. Ich hab den Ordner zwischenzeitlich mal verschoben... Aber wenn ich das korrigiere und von meinem USB-Stick auf den Computer ziehe funktioniert es immernochnicht. Ich kann einmal Enterdrücken, dann sagt er mir was in der INI steht, wenn ich dann nochmal Enter drücke kommen hübsche fehlermeldungen und ein kompliziert aussehendes Fenster mit dem Titel "CPU".
Was soll das Ganze?!^^


jaenicke - So 13.09.09 15:48

Korrigiere erst einmal deine Pfadangabe (siehe oben)...
Und dann geh zeilenweise durch und schau was wo passiert und wann der Fehler auftritt.


Andreas L. - So 13.09.09 15:52

user profile iconMister Riös hat folgendes geschrieben Zum zitierten Posting springen:
Oh mann, du hast natürlich Recht! Man kann schon dumm sein oO. Ich hab den Ordner zwischenzeitlich mal verschoben... Aber wenn ich das korrigiere und von meinem USB-Stick auf den Computer ziehe funktioniert es immernochnicht. Ich kann einmal Enterdrücken, dann sagt er mir was in der INI steht, wenn ich dann nochmal Enter drücke kommen hübsche fehlermeldungen und ein kompliziert aussehendes Fenster mit dem Titel "CPU".
Was soll das Ganze?!^^


Schon Delphi neugestartet?

Zum Code: Das kann so nicht gehen. Erstmal beginnt deine Schleife außerhalb des try-finally-Blocks. Dann speicherst du bei jedem Schleifendurchlauf in den selben Schlüssel. probiers mal so: ini.WriteString('Section_1','Wert' + IntToStr(i),Wert); Außerdem rufst du UpdateFile nach jedem Schreibvorgang auf, das ist zwar kein richtiger Fehler, beansprucht aber unnötig Rechenzeit und die Festplatte wird dabei auch nicht geschont.


Mister Riös - So 13.09.09 16:20

user profile iconAndreas L. hat folgendes geschrieben Zum zitierten Posting springen:
probiers mal so: ini.WriteString('Section_1','Wert' + IntToStr(i),Wert);


Wazu wäre das genau dann gut?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
begin
 ini := TMemIniFile.Create('I:\Chat\Wert.ini');
  try
   for I := 0 to 10 do
    begin
    readln(Wert);
    if Wert = '' then
    begin
     Ausgabe := ini.ReadString('Section_1','Wert','Fehler');
     writeln(Ausgabe);
    end
    else
    begin
     ini.WriteString('Section_1','Wert',+ IntToStr(i),Wert);
     ini.UpdateFile;
    end;
   end;
  finally
   ini.free;

 end;
 readln;
end.

Das wäre dann mein neuer Code. Das mit dem UpdateFile ist übrigens gewollt... Jetzt bekomm ich gesagt:
Mein Compiler hat folgendes geschrieben:

[Fehler] Chat.dpr(26): Operator ist auf diesen Operandentyp nicht anwendbar

Was heißt das denn jetzt schonwieder?^^


jaenicke - So 13.09.09 16:21

Vergleich mal genau den Code von user profile iconAndreas L. und deinen... :roll: :autsch:


Mister Riös - So 13.09.09 16:30

Okay, das hab ich übersehen^^
Also soweit keine Fehlermeldungen. Nur möchte ich ja, dass der Wert von "Wert" (In der INI) überschreiben wird, und nicht ein neuer Key angelegt wird. wenn ich den teil mit "+ IntToStr(i)," da wieder rausmache, kommen tonnenweise Fehlermeldungen.


Andreas L. - So 13.09.09 17:11

user profile iconMister Riös hat folgendes geschrieben Zum zitierten Posting springen:
Okay, das hab ich übersehen^^
Also soweit keine Fehlermeldungen. Nur möchte ich ja, dass der Wert von "Wert" (In der INI) überschreiben wird, und nicht ein neuer Key angelegt wird. wenn ich den teil mit "+ IntToStr(i)," da wieder rausmache, kommen tonnenweise Fehlermeldungen.


Achso, wenn du den Wert tatsächlich überschreiben willst war dein vorheriger Code (zumindest der Teil mit WriteString) schon richtig. Aber einen Sinn kann ich da nicht erkennen... Sag doch mal was genau du machen willst.


Mister Riös - So 13.09.09 18:44

Naja, wie man sich bei dem Dateinamen schon denken kann, soll das eine Art Chat werden. Ich bin noch ganz am Anfang damit, es geht hier noch grundsätzlich um das schreiben in eine INI. im grunde genommen sollen einfach 2 ausfphrungen von dem programm über diese file mit einender Kommunizieren. Die Idee die ich bis jetzt bezweckt habe wäre, dass das Programmm bei drücken der Entertaste den Key ausliest, und wenn man was schreibt, soll das Programm selbiges in dem Key speichern.
Theoretisch denke ich könnten so schon sehr primitiv 2 parallel laufende Programme informationen austauschen.


Mitmischer 1703 - So 13.09.09 18:59

Das solltest du dann aber nicht über eine Datei machen. Denn eine Datei kann nur von einem Programm geöffnet werden, Windows sperrt dann den Dateizugriff für andere Programme. Oder du müsstest die Datei immer wieder schließen - aber du weißt ja nicht wann die andere Datei drauf zugreift... :?


Mister Riös - So 13.09.09 20:00

Hmm, also das ist natürlich blöd. Natürlich werde ich es trotzdem auf den Versuch drauf ankommen lassen, schon allein aus eEhrgeiz das programm zu beenden.
Aber, mal blöd gefragt, das kann man doch bestimmt irgendwie umgehen, oder zumindest anderweitig lösen (sodass das anderswo gespeichert wird). Irgendwie müssen so Chat-Programme ja funktionieren...


jaenicke - So 13.09.09 20:03

Chatprogramme habe ja nichts mit Dateien zu tun. :?
Wie sollte das auch im Internet z.B. gehen? :shock:

Da kommunizieren Clientprogramme übers Netzwerk mit einem Server (bzw. lokal auf dem Rechner genauso).
Mehr siehe das entsprechende Tutorial [http://www.delphi-library.de/topic_60744.html].


Mister Riös - Mo 14.09.09 18:01

Nunja, aber theoretisch müsste es doch auch so klappen (Wenn man diese Deiteisperre umgeht), oder etwa nicht? Ich kenn mich überhaupt nicht aus mit sowas, ich dachte mir nur als Projekt wäre das vielleicht ganz lustig mal zu machen... Man sieht ja, ich lerne die Sprache erst.


Narses - Mo 14.09.09 18:52

Moin!

user profile iconMister Riös hat folgendes geschrieben Zum zitierten Posting springen:
Nunja, aber theoretisch müsste es doch auch so klappen (Wenn man diese Deiteisperre umgeht), oder etwa nicht?
Auf dem selben Rechner, vielleicht. Deutlich komplizierter wird es im LAN und im Internet kannst du diesen Ansatz gleich ganz vergessen. :?

user profile iconMister Riös hat folgendes geschrieben Zum zitierten Posting springen:
Ich kenn mich überhaupt nicht aus mit sowas, ich dachte mir nur als Projekt wäre das vielleicht ganz lustig mal zu machen...
Wenn du keine Ahnung davon hast, wäre es vielleicht eine gute Idee, auf die Leute zu hören, die dir dann Tipps dazu geben - z.B. das Tutorial, das user profile iconjaenicke dir gelinked hat. :idea: ;)

user profile iconMister Riös hat folgendes geschrieben Zum zitierten Posting springen:
Man sieht ja, ich lerne die Sprache erst.
Dann solltest du auch gleich klassische Fehler vermeiden - ein Chat auf Dateibasis wäre in meinen Augen einer... :)

cu
Narses


Mister Riös - Mo 14.09.09 22:14

Au, der hat gesessen^^
Ich höre gerne auf Leute die Dinge besser wissen, ich denke nur es ist der falsche Ansatz deswegen alles gleich über den Haufen zu werfen.
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Auf dem selben Rechner, vielleicht. Deutlich komplizierter wird es im LAN und im Internet kannst du diesen Ansatz gleich ganz vergessen. :?

Ich muss sagen, das hört sich so an, als ob dergleichen auf, naja, dann halt nur einem Computer, doch möglich wäre :wink:

user profile iconMister Riös hat folgendes geschrieben Zum zitierten Posting springen:
Man sieht ja, ich lerne die Sprache erst.

Das war eigentlich so gemeint, dass ich auch aus von der Idee falschen Programmen lernen kann, wie ich später in vielleicht sinnvolleren Programmen mit zum Beispel INIs arbeite.

Wie siehts denn aus? Kennt jemand eine Möglichkeit die genannte "Dateisperrung" zu umgehen?


jaenicke - Mo 14.09.09 22:20

Umgehen nein, aber du kannst halt immer warten bis du auf die Datei zugreifen kannst und das dann jeweils tun. Da aber keine direkte Kommunikation erfolgt, wie es eigentlich nötig wäre, weißt du auch nicht direkt, dass sich etwas geändert hat, sondern musst ständig nachschauen. Und das ist unter Windows der genau falsche Weg, da Windows nun einmal ereignisbasiert ist.


Mister Riös - Mo 14.09.09 22:25

Meine arme Idee verliert immer mehr an Substanz...
Wie lange dauert es denn, bis die Datei wieder freigegeben ist?


Narses - Mo 14.09.09 22:36

Moin!

user profile iconMister Riös hat folgendes geschrieben Zum zitierten Posting springen:
Meine arme Idee verliert immer mehr an Substanz...
Deine arme Idee ist bereits ohne Arme auf die Welt gekommen... :mrgreen:

user profile iconMister Riös hat folgendes geschrieben Zum zitierten Posting springen:
Wie lange dauert es denn, bis die Datei wieder freigegeben ist?
Im Ernst jetzt: Das. Ist. Unfug. :|

cu
Narses