Entwickler-Ecke

Dateizugriff - INI-Zugriffsproblem


Apo95 - Mo 31.12.12 17:02
Titel: INI-Zugriffsproblem
Liebe Community,

ich schreibe gerade ein Quiz, was auf INI-Dateien basiert. Ich habe hier allerdings das Problem, dass ich eine kleine Blockade anwenden wollte. Sollte die INI-Datei, welche di Fragen enthält, nicht vorhanden oder entstellt sein, soll eine Fehlermeldung kommen. Obwohl die Datei im rivhtigen Verzeichnis vorhaden ist, setzt es eine Fehlermeldung.

Hier ist der Source:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.cyBitBtn1Click(Sender: TObject);
begin

 if fileExists('%ProgramFiles%\EA\GoetheQuiz 2010beta\POFMEDIA\CONSET1.ggg')=false then
      if Application.MessageBox('Die erforderliche Programmdatenbank ist entstellt oder konnte nicht gefunden  werden.'+
      'Bitte führen Sie ggf. eine Reparaturinstallation durch. Das Programm wird beendet.','Fataler Fehler',mb_ICONSTOP or MB_OK)=IDOK then
      Application.Terminate;
   if fileExists('%ProgramFiles%\EA\GoetheQuiz 2010beta\POFMEDIA\CONSET1.ggg')=true then
   Form2.show;

end;


jaenicke - Mo 31.12.12 17:45

user profile iconApo95 hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
 if fileExists('%ProgramFiles%\EA\GoetheQuiz 2010beta\POFMEDIA\CONSET1.ggg')=false then                    
Das ist gleich doppelt falsch. Zum Einen musst du den Platzhalter %ProgramFiles% vorher selbst ersetzen, das passiert dort AFAIK nicht automatisch, zum Anderen ist das =false ebenfalls falsch. Hier habe ich mal ein kleines Beispiel gebastelt, wann so etwas schief geht:
http://www.delphi-forum.de/viewtopic.php?p=548760#548760
Mehr dazu steht hier:
http://www.delphi-treff.de/tutorials/objectpascal/programmierung-mit-boolean-werten/page/4/
Und warum das auch vollkommen unlogisch ist:
http://www.delphi-forum.de/viewtopic.php?p=560637#560637


Popov - Mo 31.12.12 21:14

@Apo95

Also ich will jaenicke nicht unbedingt widersprechen, aber ob  = false ist, ist diskussionsfähig. Ich würde statt falsch eher sagen, dass es nicht zu empfehlen ist. Nicht weil es als solches falsch ist, sondern, weil Delphi im Gegensatz zu anderen Sprachen mehr Möglichkeiten bietet. Ob man Boolean x mit if x = True oder einfach mit if x, bei false mit if not x vergleicht, ist erst ein mal egal und nicht falsch. Aber wie gesagt bietet Delphi mehr Möglichkeiten in der Richtung. Bei Delphi ist False 0 und True -1 als eine Art Variablen definiert. Aber sonst wird für true alles ungleich 0 akzeptiert. Somit ist false 0 und true alles andere. Trotzdem, True als Variable ist -1, als Treu-Ergebnis alles außer 0. Greift man auf fremde Daten zu, könnte eine Funktion für True eine 1 liefern. Es gibt auch Spezialisten die für True einen eigenen Wert definieren, z. B. 2. Und schon hat man für True -1, 1 und 2. Wenn man jetzt x = True vergleicht, kommt bei einem True mit dem Wert 1 ein False zurück. Dagegen tritt bei der Prüfung für Boolean x if x oder if not x das Problem nicht auf, da hier True alles außer 0 ist.

Somit abschließend, ich halte Vergleiche wie if x = True nicht für falsch, aber nicht empfehlenswert, da u. U. Fehleranfällig.

Auch würde ich den Pfad einer Variable zuweisen:


Delphi-Quelltext
1:
  QuizPath := '%ProgramFiles%\EA\GoetheQuiz 2010beta\POFMEDIA\CONSET1.ggg';                    


Dann hast du keine doppelte Pflege.

Auch Finger weg von dem Ordner ProgramFiles. Der ist nur für Programme, nicht für Daten. Wer sein System richtig konfiguriert hat, der wird keine Datei später in dem Pfad ändern können.

Besser ist der Ordner Anwendungsdaten (CSIDL_APPDATA) oder ein Unterordner in Eigene Daten (CSIDL_PERSONAL). Such zu dem Thema nach Begriffen "SpecialDirectory". Die liefern dir zu den Konstanten die Pfade zu den richtigen Ordnern.


Apo95 - Di 01.01.13 19:06

Aha... das habe ich bis jetzt nicht gewusst. Ich habe den QuizPath auf C:\ gesetzt. Wäre das so richtig:


Delphi-Quelltext
1:
2:
3:
if QuizPath := 'C:\QZGG\POFMEDIA\CONSET1.ggg' then
//....//
end;



Wäre es auch möglich, den Pfad in die eigenenen Dateien zu setzen? Wenn ja, wie müste ich das schreiben?

Besten Dank im Voraus!

...Und frohes neues Jahr!


jaenicke - Di 01.01.13 19:23

user profile iconApo95 hat folgendes geschrieben Zum zitierten Posting springen:
Wäre es auch möglich, den Pfad in die eigenenen Dateien zu setzen? Wenn ja, wie müste ich das schreiben?
Und was hätte das für einen Sinn? Dort gehören die Dateien erst recht nicht hin. Solche Dateien gehören in eines der Anwendungsdatenverzeichnisse (benutzerspezifisch oder global) und nirgends sonst hin...
http://www.delphi-library.de/viewtopic.php?p=548600
http://www.entwickler-ecke.de/viewtopic.php?p=541637


Martok - Di 01.01.13 19:47

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Dort gehören die Dateien erst recht nicht hin.
Das stimmt unter Umständen hier gar nicht.
Falls das eine statische, nicht vom User zu verändernde Liste von Fragen ist welche nur vom Installer da platziert wird, gehört die durchaus ins Programmverzeichnis (oder eventuell %CommonProgramFiles%).

Und um mal das Eingangsproblem zu lösen: da fehlt eine Runde begin/end. Das ist Delphi, nicht Python. Bei uns bringt (hier übrigens falsche) Einrückung dem Compiler nix ;)

EDIT: Blödsinn erzählt ;)


jaenicke - Di 01.01.13 20:28

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Und um mal das Eingangsproblem zu lösen: da fehlt eine Runde begin/end.
Die Logik stimmt schon so wie sie ist, ohne begin..end. ;-)

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Dort gehören die Dateien erst recht nicht hin.
Das stimmt unter Umständen hier gar nicht.
Falls das eine statische, nicht vom User zu verändernde Liste von Fragen ist welche nur vom Installer da platziert wird, gehört die durchaus ins Programmverzeichnis (oder eventuell %CommonProgramFiles%).
Das ist natürlich richtig, auch wenn sie auch dann in der Regel besser in den Anwendungsdaten aufgehoben sind, da die bei einem Systemupgrade und bei einer Netzwerkanmeldung übernommen werden (die unter Roaming)...


Martok - Di 01.01.13 20:38

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Die Logik stimmt schon so wie sie ist, ohne begin..end. ;-)
Oh. Ähm, stimmt natürlich :oops: Ich schieb das einfach mal auf das seltsame doppel-if :roll:


Apo95 - Sa 05.01.13 20:33

Ich verstehe bis jetzt noch nicht, was ihr meint... also: verstanden habe ich, dass das "false" nicht zu empfehlen ist; aber den Pfad einer Variablen zuweisen... welcher Datentyp wäre denn der Richtige? String?


jaenicke - Sa 05.01.13 22:29

Ja, das ist ja eine Zeichenfolge, deshalb passt String als Datentyp schon.

Was du ändern musst, ist, dass du den Ordner zuerst dir holst und den dann danach komplett für FileExists usw. nutzt.


Mathematiker - So 06.01.13 00:51

Hallo,
ich habe den Eindruck, dass Du im Moment nicht so richtig weißt, was Du machen sollst.
Versuche es doch erst einmal mit

Delphi-Quelltext
1:
2:
3:
var QuizPath:string;
...
   QuizPath:=extractfilepath(application.exename);

Die Variable QuizPath enthält dann den Ordner Deiner Exe. Deine Datei wäre damit

Delphi-Quelltext
1:
   dateiname:=quizpath+'CONSET1.ggg';                    

d.h., sie muss im gleichen Ordner wie Deine Exe liegen. Dies ist natürlich, wie jaenicke schon ausgeführt hat, nicht so schön, aber, wenn der Programmanwender nur die Daten lesen soll und nicht schreiben, geht es für den Anfang schon.

Schwierigkeiten kannst Du noch bekommen, wenn Du 'CONSET1.ggg' tatsächlich als ini-Datei auswertest.
Bei Zugriff auf die Datei benötigst Du dann, selbst wenn nur gelesen wird, volle Schreib- und Leserechte auf den Ordner. Und das kannst Du bei den Anwendern nicht vorraussetzen.
In diesem Fall würde ich Dir die Verwendung einer Textdatei (textfile) empfehlen. Diese kannst Du mit reset auch ohne Schreibrechte zum Datenlesen öffnen.

Beste Grüße
Mathematiker


Delphi-Laie - So 06.01.13 01:18

user profile iconApo95 hat folgendes geschrieben Zum zitierten Posting springen:
Ich verstehe bis jetzt noch nicht, was ihr meint... also: verstanden habe ich, dass das "false" nicht zu empfehlen ist;


Nicht zu empfehlen ist der Vergleich auf false und true, also =false bzw. =true. Vielleicht auch <>false und <>true oder gar nur mit den Operatoren < und > (welchen Sinn hätte letzteres)?

Logisch falsch ist =true und =false nicht, allerdings redundant und mithin unelegant, denn mit if, while und until werden die bool(e)sche bzw. Wahrheitswerte schon ermittelt.

Falsch wird es erst in bezug auf die Compilereigenheiten.

Für mich ist das ganz klar ein Compilerfeher, denn derartige redundate Vergleiche sind häufig (nicht jeder ist Informatiker). Wenigstens Warnungen, daß ein Wahrheitswert unnötig mit true oder false verglichen wird, könnte man vom Compiler erwarten.

Es gibt auf die Frage, ob =true und =false richtig bzw. falsch ist, paradoxerweise zwei richtige Antworten - alles eine Frage der Betrachtung.

Auf die Frage, wann der richtige Zeitpunkt gekommen ist, sich einen neuen Computer (oder alternativ ein anderes hochkomplexes elektronisches Gerät) zu kaufen, gibt es sogar drei richtige Antworten: Jetzt, immer oder nie!


jaenicke - So 06.01.13 09:28

[OT]
user profile iconDelphi-Laie hat folgendes geschrieben Zum zitierten Posting springen:
Falsch wird es erst in bezug auf die Compilereigenheiten.

Für mich ist das ganz klar ein Compilerfeher
Dann kannst du das ja den diversen Compilerherstellern schreiben. Dazu noch den ganzen Browserherstellern, dass deren JavaScript Interpreter falsch sind. Ich weiß nicht wem noch alles.
Denn das hat ja nichts mit Delphi zu tun, sondern ist nun einmal so definiert. False ist 0, alles andere ist True. Schon aufgrund der Hardware, denn die CPU kann nun einmal kein einzelnes Bit ansprechen.

Und für den Compiler hieße eine automatische Korrektur, dass jeder Zugriff auf einen Booleanwert entsprechend behandelt werden müsste, was die Ausführungsgeschwindigkeit aller Programme reduzieren würde. Und das nur wegen eines Programmierfehlers?

In JavaScript kannst du das auch leicht testen, einfach im Browser auf der Konsole eingeben:

JavaScript-Quelltext
1:
2:
3:
var a = -4;
if (a) alert('a ist true'); else alert('a ist false'); // es wird "a ist true" angezeigt
if (a == true) alert('a ist == true'); else alert('a ist nicht == true'); // es wird "a ist nicht == true" angezeigt
Passiert so in allen Browsern. Und das ist auch korrekt so.
[/OT]

Aber zurück zum Thema:
Ich hatte ja oben auch meine Units verlinkt, mit denen der Zugriff gekapselt wird, und mit denen man recht einfach die Einstellungen nutzen kann ohne selbst viel dazu zu entwickeln.


Delphi-Laie - So 06.01.13 12:07

jaenicke, daß ein (jeder) digitaler Computer der Architektur "PC", vor allem dessen Prozessor, nur 0 und 1 (und das als kleinstmögliche Verpackung in ein Byte mit 7 anderen Bits verpackt) kennt, weiß ich selbst.

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Und für den Compiler hieße eine automatische Korrektur, dass jeder Zugriff auf einen Booleanwert entsprechend behandelt werden müsste, was die Ausführungsgeschwindigkeit aller Programme reduzieren würde. Und das nur wegen eines Programmierfehlers?


Was schrieb ich weiter oben? Zur Not reicht auch eine Warnung des Compilers (also während des Compilierens ausgegeben) aus, daß boolsche Variablen verglichen werden! Das muß keinen Einfluß auf das Compilat und mithin auf dessen Ablaufgeschwindigkeit haben!