Autor Beitrag
bf109g.01
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 84



BeitragVerfasst: Mi 23.03.11 00:18 
Hallo, ich benutze für mein Programm eine INI-Datei.
Nun habe ich folgendes Problem.

- Beim Programmstart soll die INI ausgelesen werden.
- Ist keine vorhanden, soll eine erzeugt, mit Standardwerten beschrieben und abgespeichert werden.
- Die Datei wird zwar erzeugt, ist danach aber immer leer. Erst wenn man das gesamte Programm neustartet, funktioniert das GAnze.

Was muss ich da jetzt bitte ändern?

ausblenden volle Höhe 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:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
type Spieler= record
              Name   : string[15];
              color: Tcolor;
              Games: Integer;
              end;
Speicherfeld=array [1..3of Spieler;
var
  Speicher       : Speicherfeld;
  Player1, Player2, AllgPlayer: Spieler;
// --------------------------------------------------------------
procedure TForm_Spiel.StartDaten_einlesen;
var Save: File of Speicherfeld;
    path: string;
begin
  path:=ExtractFilePath(ParamStr(0))+'\config.ini';
  if not fileexists(path) then
    begin
      Filecreate('config.ini');
      MessageDlg('File "config.ini" can not be found.', mtError, [mbok], 0);
      Standardsettings;
      Spiel_Speichern;
    end
  else
    begin
      AssignFile(Save,Path);
      Reset(Save);
        read(Save,Speicher);
      CloseFile(Save);

      Player1:=Speicher[1];
      Player2:=Speicher[2];
      AllgPlayer:=Speicher[3];
    end;

  En1.Text:=Player1.name;
  En2.Text:=Player2.name;
  Pf1.color:=Player1.color;
  Pf2.color:=Player2.color;
end;

procedure TForm_Spiel.Standardsettings;
begin
  Player1.name:='Player 1';
  Player1.color:=clred;
  Player2.name:='Player 2';
  Player2.color:=clblue;
  AllgPlayer.Games:=0;
end;

procedure TForm_Spiel.Spiel_Speichern;
var Save: File of Speicherfeld;
    path: string;
begin
  Speicher[1]:=Player1;
  Speicher[2]:=Player2;
  Speicher[3]:=AllgPlayer;

  path:=ExtractFilePath(ParamStr(0))+'\config.ini';

  AssignFile(Save,path);
  Rewrite(Save);
    write(Save,Speicher); // "E/A-Fehler 32" an dieser Stelle wird eben in die neue Datei nicht hineingeschrieben
  CloseFile(Save);
end;
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Mi 23.03.11 01:16 
E/A-Fehler 32 = "The process cannot access the file because it is being used by another process." Siehe: msdn.microsoft.com/e...ms681382(VS.85).aspx
So wie ich das sehe, wird nach dem FileCreate die Datei nicht geschlossen. Wenn Du dann versuchst, die Datei nochmals zu öffnen, knallt es.
Warum wertest Du nicht die Rückgabewerte der Funktionen aus?
Auszug aus der Hilfe zu FileClose: "Mit FileClose kann eine Datei anhand ihres Handles geschlossen werden. Sie erhalten das Handle beim Öffnen der Datei mit FileOpen oder FileCreate."

Für diesen Beitrag haben gedankt: bf109g.01
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 23.03.11 07:13 
Du kannst die Hilfe auch einfach verlinken. ;-)
docwiki.embarcadero....e/SysUtils.FileClose
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6393
Erhaltene Danke: 147

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mi 23.03.11 09:14 
Das CreateFile ist überflüssig und die Ursache des Fehlers.
Rewrite sorgt schon dafür, dass die Datei angelegt wird, falls diese nicht existiert.

btw:
Das ist keine INI-Datei, sondern eine typisierte Datei. :wink:

Für diesen Beitrag haben gedankt: bf109g.01
bf109g.01 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 84



BeitragVerfasst: Mi 23.03.11 18:37 
user profile iconjasocul hat folgendes geschrieben Zum zitierten Posting springen:
btw:
Das ist keine INI-Datei, sondern eine typisierte Datei. :wink:
Dann wäre es doch auch sehr geistreich, die Datei nicht als *.ini anzulegen, denke ich.
Welchen Typ nimmt man dann standardmäßig stattdessen? *.dat?

Werde jetzt einfach mal das Filecreate rausschmeißen und schauen, was geschieht. :)
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 23.03.11 18:41 
user profile iconbf109g.01 hat folgendes geschrieben Zum zitierten Posting springen:
Welchen Typ nimmt man dann standardmäßig stattdessen? *.dat?
Die Endung gibt es schon in Windows selbst, ich würde z.B. .gameconfig oder so etwas nehmen.
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Mi 23.03.11 18:48 
Zitat:
Dann wäre es doch auch sehr geistreich, die Datei nicht als *.ini anzulegen, denke ich.
Warum nimmst Du nicht TIniFile (Unit IniFiles)? Wie ich sehe, hast du doch nur Strings und Zahlen zu speichern. Auch Color ist nix anderes als eine Zahl.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 23.03.11 19:12 
Besser ist dann TMemIniFile (wenn schon INIs benutzt werden). Denn TIniFile benutzt die alten Windows API Routinen aus der 16-Bit Zeit vor 20 Jahren (woher ja auch INIs stammen). Die sind erstens als deprecated markiert und dementsprechend vielleicht z.B. in Windows 8 schon nicht mehr da und zweitens musste ich feststellen, dass die auch nicht immer wie gewünscht arbeiten.

TMemIniFile benutzt eigene Implementierungen (zumindest unter Delphi XE) und arbeitet korrekt.

Davon abgesehen würde ich eher XML-Dateien nehmen, zum Beispiel mit meiner entsprechenden Unit, die das alles kapselt:
www.delphi-forum.de/viewtopic.php?t=92348
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Mi 23.03.11 20:22 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Besser ist dann TMemIniFile (wenn schon INIs benutzt werden). Denn TIniFile benutzt die alten Windows API Routinen aus der 16-Bit Zeit vor 20 Jahren (woher ja auch INIs stammen). Die sind erstens als deprecated markiert und dementsprechend vielleicht z.B. in Windows 8 schon nicht mehr da und zweitens musste ich feststellen, dass die auch nicht immer wie gewünscht arbeiten.
Weder in der XE-Hilfe ms-help://embarcadero.rs_xe/vcl/IniFiles.TCustomIniFile.ReadInteger.html noch bei docwiki.embarcadero.....TIniFile.ReadString ist ein entsprechender Hinweis zu finden. Ich arbeite hier problemlos mit IniFiles unter XE und Windows 32. Außerdem hat TMemInifile gegenüber TIniFile den Nachteil, daß die Schreibzugriffe gecached werden.
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Davon abgesehen würde ich eher XML-Dateien nehmen
Ich hasse die Dinger ...
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 23.03.11 20:37 
user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:
Weder in der XE-Hilfe ms-help://embarcadero.rs_xe/vcl/IniFiles.TCustomIniFile.ReadInteger.html noch bei docwiki.embarcadero.....TIniFile.ReadString ist ein entsprechender Hinweis zu finden.
Dort nicht, aber bei den API-Funktionen, die diese Methoden benutzen. Und wenn die nicht mehr funktionieren irgendwann, funktionieren logischerweise auch alle Programme, die diese Funktionen nutzen, nicht mehr.
msdn.microsoft.com/e...724353(v=vs.85).aspx hat folgendes geschrieben:
Note This function is provided only for compatibility with 16-bit Windows-based applications.
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Do 24.03.11 01:04 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Dort nicht, aber bei den API-Funktionen, die diese Methoden benutzen. Und wenn die nicht mehr funktionieren irgendwann,[...]
Bis dahin wird noch sehr viel Wasser den Main hinunter fließen ...
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 24.03.11 06:50 
user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:
Bis dahin wird noch sehr viel Wasser den Main hinunter fließen ...
Vermutlich, aber wissen kann man das nicht. Schließlich sind bei 64-Bit Systemen diese Funktionen nicht mehr notwendig, da 16-Bit Programme ohnehin nicht mehr funktionieren. Sobald es also keine 32-Bit Version von Windows mehr gibt, macht es auch keinen Sinn mehr diese Funktionen zu behalten.

Davon abgesehen gibt es schließlich eine Alternative, die nicht auf diesen API Funktionen aufsetzt. Zudem einmal als Beispiel:
ausblenden Quelltext
1:
2:
[Test]
a="Test","Nichts"
Was kommt bei ReadString wohl heraus?
Bei TIniFile: Test","Nichts
Bei TMemIniFile: "Test","Nichts"
Das ist nur eines der Probleme, die TIniFile bei mir bereits gemacht hat...