Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Textfiles Verständnisfrage & Frage (https://www.delphipraxis.net/184131-textfiles-verstaendnisfrage-frage.html)

Grayknife 28. Feb 2015 22:24

Textfiles Verständnisfrage & Frage
 
Hallo DPler,
Ich möchte gerne eine Variable mit Integerwert, also zb. einfach 14 extern in einer Textdatei speichern. Dazu habe ich folgende Prozedur entwickelt:

Delphi-Quellcode:
procedure TForm1.Speichern;
 var Speicher: Textfile;
     GesH:Integer;
begin

 Try
   Reset(Speicher,'Speicher.txt');
   Readln(Speicher,GesH);
   GesZ:=GesH + GesZ;
 Except
   AssignFile(Speicher,'Speicher.txt');
 End;
 Rewrite(Speicher);
 Writeln(Speicher,GesZ);
 CloseFile(SPeicher);
end;
Dabei soll erst geschaut werden ob es die Datei schon gibt. Wenn ja wird in der Datei der Integerwert rausgelesen und in GesH gespeichert. Anschließend wird GesZ mit GesH addiert und in GesZ gespeichert.
Wenn keine datei mit dem Namen Speicher.txt existiert soll in der except schleife eine erstellt werden. Anschließend wird der Zeiger auf ganz oben gestellt, das neue GesZ bzw. das existierende in der 1. zeile gespeichert, und dann geschlossen.

Sind meine Überlegungen richtig?
denn es gibt 1 komischen Fehler:
1. Wenn keine Datei existiert, wird mir trotzdem ein Fehler angezeigt, das die Datei nicht gefunden wurde, aber eigentlich müsste doch durch AssignFile eine erstellt werden? :?:

Uwe Raabe 28. Feb 2015 22:35

AW: Textfiles Verständnisfrage & Frage
 
Welche Delphi-Version verwendest du?

himitsu 28. Feb 2015 23:03

AW: Textfiles Verständnisfrage & Frage
 
FreePascal/Lazarus?
Delphi kennt kein derartigen Reset-Befehl (in der System.pas)

Zitat:

Wenn keine Datei existiert, wird mir trotzdem ein Fehler angezeigt
Wer zeigt den Fehler?
  • Welche Codezeile?
  • Der Debugger und/oder das Programm?

Fehler/Denkfehler:
  • AssignFile erstellt nichts, es initialisiert nur die Datei-Variable.
    Rewrite, Delphi-Referenz durchsuchenReset, Append öffnen/erstellen die Datei.
    Zitat:

    aber eigentlich müsste doch durch AssignFile eine erstellt werden
    Du hast bestimmt nicht die OH gelesen.
  • Man steuert nicht mit "Ausnahmen" den normalen Programmfluss. :warn:
    FileExists, IOResult oder Dergleichen?
  • Wenn die Datei von Reset geöffent wurde, wer schließt die dann wieder, bevor die nächten Dateioperationen (AssignFile/Rewrite) los gehn?

Luckie 28. Feb 2015 23:56

AW: Textfiles Verständnisfrage & Frage
 
Interessant wäre auch: Wo landet die Datei ohne Pfad Angabe? :roll:

Uwe Raabe 1. Mär 2015 10:20

AW: Textfiles Verständnisfrage & Frage
 
Zitat:

Zitat von himitsu (Beitrag 1291895)
FreePascal/Lazarus?
Delphi kennt kein derartigen Reset-Befehl (in der System.pas)

Genau! Interessant ist aber die Fehlermeldung des Compilers (XE7):

Zitat:

E2158 System-Unit veraltet oder beschädigt: '@assign' fehlt

Klaus01 1. Mär 2015 11:43

AW: Textfiles Verständnisfrage & Frage
 
Hallo,

Reset gibt es auch in Delphi.

Allerdings muss auch ein AssignFile durchgeführt werden, wenn die Datei mit Reset geöffnet wird.
Beispiel hier.

Grüße
Klaus

Sir Rufo 1. Mär 2015 11:49

AW: Textfiles Verständnisfrage & Frage
 
@Klaus01

Niemand hat behauptet, dass es
Delphi-Quellcode:
Reset
in Delphi nicht gibt.

himitsu hat gesagt, dass es allerdings kein
Delphi-Quellcode:
Reset
gibt, dass so
Delphi-Quellcode:
Reset( Speicher, 'Speicher.txt' );
aufgerufen werden kann. ;)

Grayknife 1. Mär 2015 13:58

AW: Textfiles Verständnisfrage & Frage
 
Ahh, so schnell so viele Antworten :shock: :-D

Also:
@Uwe Raabe, Hier ein Ausschnitt von der Info über Borland Delphi: "Borland® Delphi® für Microsoft® Windows™ Version 10.0.2288.42451 Update 2 Copyright © 2005 Borland® Software Corporation." -> Also Version 10 !?

@himitsu, Sry, das war viel zu oberflächlich der Fehler: Das Programm lässt sich mit dem Debugger einwandfrei starten, Erst wenn die Prozedur ausgeführt wird, Kommt eine Infobox, wo ich das Programm Anhalten,Fortsetzen kann mit der Meldung: "Im Projekt Project1.exe ist eine Exception der KLasse EInOutError mit der Meldung "Datei nicht gefunden" aufgetreten." -> Also eine Benachrichtigung über die Debugger-Exception?!

Verstehe ich das richtig, dass ich nicht die Try-Except-Schleife verwenden kann? -> Muss ich dann eher eine If Fileexists=True then ... -Schleife verwenden?

@Luckie, Also so wie ich das immer überlege müsste sie in dem Ordner, wo sich die .Exe befindet, erstellt werden. Dachte ich mir immer jedenfalls ^^.

@Klaus01, Also kopiere ich einfach den Code aus dem Beispiel und bastel ihn in bei mir mit rein?

@Sir Rufo, Warum kann das Reset nicht so
Delphi-Quellcode:
Reset(Speicher,'Speicher.txt')
aufgerufen werden?

Sir Rufo 1. Mär 2015 14:11

AW: Textfiles Verständnisfrage & Frage
 
Weil die Dokumentation das sagt?

Delphi: http://docwiki.embarcadero.com/Libra...e/System.Reset
FPC: http://www.freepascal.org/docs-html/...tem/reset.html

Grayknife 1. Mär 2015 14:26

AW: Textfiles Verständnisfrage & Frage
 
@Sir Rufo, okey, also einfach nur
Delphi-Quellcode:
Reset(Speicher)
? Aber das verstehe ich jetzt nicht :D Oder doch... also dann ändere ich jetzt den Code zu:
Delphi-Quellcode:
procedure TForm1.Speichern;
 var Speicher: Textfile;
     GesH:Integer;
begin
GesH:=0;
   AssignFile(Speicher,'Speicher.txt');
   Reset(Speicher);
   Readln(Speicher,GesH);
   GesZ:=GesH + GesZ;
 Rewrite(Speicher);
 Writeln(Speicher,GesZ);
 CloseFile(SPeicher);
end;
Okey, mit AssignFile weise ich also der Variablen Speicher einfach Speicher.txt zu?! Und wie kann ich jetzt eine Text Datei erstellen? o.0

SMO 1. Mär 2015 14:39

AW: Textfiles Verständnisfrage & Frage
 
Müsste Delphi 2005 oder 2006 sein.

Exceptions sind Ausnahmen und keine Schleifen. Man sollte try-finally Blöcke benutzen, um Resourcen zu schützen, try-except Blöcke um spezielle Exceptions zu behandeln, aber nicht um ALLE Exceptions zu "verschlucken".

Dein Code sollte ungefähr so aussehen:

Delphi-Quellcode:
var
  Speicher: Textfile;
  GesH: Integer;
begin
  AssignFile(Speicher, 'Speicher.txt');
{$I-}
  Reset(Speicher);
{$I+}
  try
    if IOResult = 0 then
      Readln(Speicher, GesH)
    else
      GesH := 0; // oder sonstiger Standardwert
    GesZ := GesH + GesZ + 1;
    Rewrite(Speicher);
    Writeln(Speicher, GesZ);
  finally
    CloseFile(Speicher);
  end;
Erklärung:
Du musst zuerst per AssignFile der Textfile-Variable den Dateinamen zuweisen. Sonst geht gar nichts. Du kannst ja auch nicht mit dem Auto losfahren, ohne vorher den Motor anzulassen.
Per {$I-} wird der Compiler angewiesen, keine Exceptions zu generieren wenn bei Dateioperationen wie Reset Fehler auftreten (z.B. Datei existiert nicht). Mit {$I+} generiert er dann wieder Exceptions für Dateioperationen. Also deaktivieren wir das hier nur kurz für den Reset-Aufruf. Wir müssen dann aber selbst über IOResult prüfen, ob Reset erfolgreich war oder nicht. Bei Erfolg ist der Wert 0, und du kannst per Readln aus der Datei lesen. Bei Fehler wird deine GesH-Variable mit einem Standardwert initialisiert.

Rewrite öffnet die Datei dann zur Ausgabe (ein vorheriges CloseFile ist nicht erforderlich) und löscht sie dabei komplett.
Der try-finally Block hier sorgt dafür, dass CloseFile in jedem Fall aufgerufen wird, selbst wenn bei Readln, Rewrite oder Writeln Exceptions auftreten! Da du einen Integer (GesH) liest, würde Readln z.B. eine Exception erzeugen, wenn in der Datei kein Zahlenwert, sondern ein Buchstabe oder so drin steht. Wenn du diesen Fall behandeln möchtest, musst du auch um Readln einen {$I-}..{$I+} Block setzen und IOResult nach Readln prüfen...

Aber warum sich plagen und mit diesen Uralt-Routinen Dateien lesen? Es kann durchaus Gründe dafür geben, z.B. wenn man das Programm so klein wie möglich halten will, keine VCL benutzt usw. Aber normalerweise geht es einfacher. Benutze TStream und seine Nachfahren (TStringStream), oder warum nicht INI-Dateien?

Delphi-Quellcode:
uses
  IniFiles;

var
  GesZ: Integer;

procedure TForm1.Speichern;
var
  Speicher: TIniFile;
  GesH: Integer;
begin
  Speicher := TIniFile.Create('Speicher.txt');
  try
    GesH := Speicher.ReadInteger('Variablen', 'GesH', 0);
    GesZ := GesH + GesZ;
    Speicher.WriteInteger('Variablen', 'GesH', GesZ );
  finally
    Speicher.Free;
  end;
end;

Perlsau 1. Mär 2015 16:13

AW: Textfiles Verständnisfrage & Frage
 
Zitat:

Zitat von Grayknife (Beitrag 1291892)
Ich möchte gerne eine Variable mit Integerwert, also zb. einfach 14 extern in einer Textdatei speichern.

Ein bißchen Grundlagenwissen kann nicht schaden:

Grayknife 1. Mär 2015 17:59

AW: Textfiles Verständnisfrage & Frage
 
@Perlsau, ja Grundlagenwissen ist immer guuuut (y) ;)

@SMO, erstmal vielen Dank, für die ausführliche Erklärung! :D Tjaa, warum sich plagen.. -.-'' Da wir nichts anderes gelernt haben in der Schule ;) Und wenn ich etwas nicht verstehe, nehme ich das, was ich verstehe :D siehe z.b.: http://forum.giga.de/web-entwicklung...speichern.html Und was du jetzt vorschlägst, schaut so ähnlich aus wie die letzte Möglichkeit aus dem Link. Dann schaue ich mir jetzt deinen Vorschlag genauer an unter dem Schlagwort TStringstream, ok? Und .ini-Dateien sind das nicht verschlüsselte Dateien oder sowas? :D . In der Schule haben wir gelernt, "Wenn du ein Programm schreiben möchtest, öffne zuerst Delphi und klicke dann auf Datei->Neu->VCL Formularanwendung". Aber wie ich jetzt rauslese, gibt es vieeel mehr Möglichkeiten mit Delphi?!

Perlsau 1. Mär 2015 18:17

AW: Textfiles Verständnisfrage & Frage
 
Zitat:

Zitat von Grayknife (Beitrag 1291935)
Aber wie ich jetzt rauslese, gibt es vieeel mehr Möglichkeiten mit Delphi?!

In der Tat :!:

Am besten du machst es mit einer Stringliste, wobei du DateiName (String) selber festlegen mußt:
Delphi-Quellcode:
Procedure TForm1.Speichern;
Var
  Liste : TStringList;
begin
  Liste := TStringList.Create;
  Try
    Liste.Append(Edit1.Text);
    Liste.SaveToFile(DateiName);
  Finally
    Liste.Free;
  End;
end;

SMO 1. Mär 2015 18:28

AW: Textfiles Verständnisfrage & Frage
 
INI-Dateien sind reine Textdateien. Ursprünglich haben Windows-Programme sie benutzt, um INItialisierungswerte und Einstellungen zu speichern. Dann hat aber Microsoft die Entwickler dazu aufgefordert, solche Einstellungen stattdessen in der Registry zu speichern. Aber auch heute gibt es noch gute Gründe, INI-Dateien zu benutzen. Sie sind einfach editierbar und portabel (d.h. sie können zusammen mit dem Programm auf andere Rechner kopiert werden und die Einstellungen sind dort also auch sofort verfügbar).

Probier den Code doch einfach mal aus. Die erstellte Datei sollte damit so aussehen:
Code:
[Variablen]
GesH=123
"Variablen" ist der Name des Abschnitts. Es kann mehrere Abschnitte in einer Datei geben, sie brauchen eindeutige Namen. "GesH" ist der Name des Schlüssels und "123" sein Wert.

Viele Wege führen nach Rom. Aber nicht alle sind gleich gut bei einer gegebenen Problemstellung.
Du solltest dir TStream und seine Nachfahren (TFileStream, TMemoryStream, TStringStream) wirklich anschauen, aber für deine Zwecke hier (eine Zahl in eine Datei speichern und wieder auslesen) könnte TIniFile (oder TMemIniFile) die komfortabelste Lösung sein. Denn damit wird das Konvertieren deines Integers in einen String und zurück automatisch übernommen. Und wenn die Datei nicht existiert oder der Wert kein Integer ist, dann wird keine Exception ausgelöst, sondern einfach der Standardwert benutzt (der letzte Parameter von TIniFile.ReadInteger).
Mit einem Stream musst du dich selbst um solche Dinge kümmern. Du könntest natürlich auch den Binärwert des Integers in eine Datei schreiben (TFileStream.WriteBuffer), aber das wäre dann keine Textdatei mehr.

Perlsau 1. Mär 2015 18:44

AW: Textfiles Verständnisfrage & Frage
 
Sorry, SMO, aber wir haben's hier mit einem Schüler zu tun, der kaum das notwendigen Grundlagenwissen mitbringt, um deinen Ausführungen folgen zu können.

SMO 1. Mär 2015 19:02

AW: Textfiles Verständnisfrage & Frage
 
Zitat:

Zitat von Perlsau (Beitrag 1291944)
Sorry, SMO, aber wir haben's hier mit einem Schüler zu tun, der kaum das notwendigen Grundlagenwissen mitbringt, um deinen Ausführungen folgen zu können.

Man muss die Leute nicht gleich für dumm halten. Wenn Grayknife etwas nicht versteht, das ich geschrieben habe, kann er/sie einfach nochmal nachfragen.
In der Zwischenzeit darfst du erklären, wie Grayknife die GesH oder GesZ Integer aus dem ursprünglichen Programmschnipsel mit deinem Edit1.Text kombinieren kann. Aber bitte nicht überfordern! :cyclops:

Grayknife 1. Mär 2015 19:46

AW: Textfiles Verständnisfrage & Frage
 
@SMO achso, es sind trotzdem Dateien die mit .txt enden, aber "anders" gelesen werden da sie über andere Funktionen aufgerufen werden, hier mit ini&so. So wie es sich anhört sollte ich TiniFile ausprobieren, das hat dann nichts mehr mit ..Stream.. zu tun?

@Perlsau, Ja vielleicht verstehe ich nicht auf Anhieb alles, aber ich versuche es zu verstehen und umzusetzen. Und wenn ich nachfrage, ist das nicht der Faulheit halber, sondern eine Verständnisfrage! Denn meißtens ist es auf den Seiten so umständlich erklärt, dass man nicht EINE Sache versteht, obwohl man sich bemüht es zu verstehen. Und wenn man anfängt zu hinterfragen, warum ich genauer nachfrage und nicht selber google, dann würde all das hier sinnlos sein, alles was uns umgibt :roll: (denke ich mir jedenfalls)

Perlsau 1. Mär 2015 20:17

AW: Textfiles Verständnisfrage & Frage
 
Zitat:

Zitat von SMO (Beitrag 1291952)
Man muss die Leute nicht gleich für dumm halten.

Sorry, aber ich habe niemanden für dumm gehalten. Du darfst deinen Unterstellungsversuch daher gerne wieder einstecken.

Zitat:

Zitat von SMO (Beitrag 1291952)
Wenn Grayknife etwas nicht versteht, das ich geschrieben habe, kann er/sie einfach nochmal nachfragen. In der Zwischenzeit darfst du erklären, wie Grayknife die GesH oder GesZ Integer aus dem ursprünglichen Programmschnipsel mit deinem Edit1.Text kombinieren kann. Aber bitte nicht überfordern! :cyclops:

Das war ein Beispiel. Beispiele sind keine fix&fertigen Quelltexte.

Zitat:

Zitat von Grayknife (Beitrag 1291957)
@Perlsau, Ja vielleicht verstehe ich nicht auf Anhieb alles, aber ich versuche es zu verstehen und umzusetzen. Und wenn ich nachfrage, ist das nicht der Faulheit halber, sondern eine Verständnisfrage! Denn meißtens ist es auf den Seiten so umständlich erklärt, dass man nicht EINE Sache versteht, obwohl man sich bemüht es zu verstehen. Und wenn man anfängt zu hinterfragen, warum ich genauer nachfrage und nicht selber google, dann würde all das hier sinnlos sein, alles was uns umgibt :roll: (denke ich mir jedenfalls)

Es hat doch keiner gefragt, warum du genauer nachfragst, und es hat dich auch keiner aufgefordert, selber zu googlen. Den zweiten Halbsatz mit dem "sinnlos" hab ich leider nicht einordnen können.

Okay, nicht meine Ebene, ich blende mich hier aus.

SMO 1. Mär 2015 20:19

AW: Textfiles Verständnisfrage & Frage
 
Richtig, TIniFile hat nichts mit TStream zu tun. Deine ursprüngliche Herangehensweise mit AssignFile, Reset, Rewrite, Readln und Writeln funktioniert so schon seit über 30 Jahren, seit dem ursprünglichen Turbo Pascal, das Delphis Vorfahre war. Die hier vorgeschlagenen Lösungen mit TIniFile, TStream und auch TStringList sind alle "moderner" und basieren auf sogenannten Klassen/Objekten. Aber hier jetzt die Details objektorientierter Programmierung zu erörtern ginge in der Tat zu weit. Wenn du die alte Herangehensweise nicht benutzen musst, dann können Klassen bequemer sein.

Ini-Dateien haben gewöhnlich die Dateiendung .ini, also z.B. "Speicher.ini", aber es sind immer Textdateien, also ist es kein Problem auch .txt zu benutzen.

Wie von mir angedeutet ist der Code von Perlsau unvollständig, würde aber prinzipiell auch funktionieren. Bei ihm fehlt das Lesen aus der Datei sowie die Typumwandlung von string nach Integer und umgekehrt.

Luckie 2. Mär 2015 02:56

AW: Textfiles Verständnisfrage & Frage
 
Zitat:

Zitat von Grayknife (Beitrag 1291912)
@Luckie, Also so wie ich das immer überlege müsste sie in dem Ordner, wo sich die .Exe befindet, erstellt werden. Dachte ich mir immer jedenfalls ^^.

Da hast du falsch gedacht. Es wird das aktuelle Verzeichnis genommen. Und das ist nicht unbedingt das, in dem die Anwendung liegt. Diese kann schon von einem Datei-Öffnen-Dialog geändert werden:
Delphi-Quellcode:
0procedure TForm4.btn1Click(Sender: TObject);
begin
 if OpenDialog1.Execute then
   Self.Caption := GetCurrentDir;
end;
Und wen ich mir jetzt noch die Meldung der Exception angucke, dass eine Datei nicht gefunden wurde, dann würde ich jetzt davon ausgehen, dass deine Anwendung die Datei im falschen Verzeichnis sucht und da natürlich nicht findet.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:32 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz