Append bei Textdatei bringt error

Für allgemeine Fragen zur Programmierung, welche nicht! direkt mit Lazarus zu tun haben.
Bergmensch
Beiträge: 13
Registriert: Do 6. Mai 2021, 18:16

Append bei Textdatei bringt error

Beitrag von Bergmensch »

Hallo allerseits!

Habe für mein Problemchen sehr lange im Netz gesucht und natürlich auch hier im Forum, aber keine passende Hilfe gefunden.
Darum wende ich mich hoffnungsvoll an euch!
Mein Problemchen:

Ich möchte für eine Messtechnikanwendung Messwerte in ein Textfile schreiben.
Wenn die Datei mit den Messwerten noch nicht existiert, wird sie erstellt, andernfalls sollen die neuen Messwerte mit append
an das Ende der bestehenden Textdatei hinzugefügt werden.
Compilieren funktioniert ohne Fehlermeldung aber bei der Ausführung gibt`s bei Append die Fehlermeldung, dass das
File nicht existiert! Ist echt schräg, weil beim FileExists kommt er drüber....
Bitte um eure Hilfe!

Hardware: Raspberry Pi 4
Betriebssystem Raspbian Buster
Lazarus 2.0.0
FPC 3.0.4

Mein Code:

Code: Alles auswählen

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
  fileutil;

type

  { TForm1 }

  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Timer1: TTimer;
    Timer2: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

var
  i:integer;

{$R *.lfm}

procedure Messwerte_schreiben();

var
  DateiName, Pfad     :String;
  DatumUhrzeitString  :String;
  Datei               :Textfile;

begin
  DatumUhrzeitString:=FormatDateTime('yyyy.mm.dd hh:nn:ss', now);

  DateiName:='Test.txt';
  Pfad:= ExtractFilePath(paramstr(0));

  if not DirectoryExists(Pfad+DateiName) then
     ForceDirectories(Pfad+'Daten');

  if FileExists(Pfad+'Daten/'+DateiName) then
     begin
       AssignFile(Datei,Pfad+'Test.txt');
       try
         Append(Datei);
       except
         on E: EInOutError do
            Form1.Label3.Caption:=E.Message;
       end;

       Form1.Label1.Caption:=Pfad;
       Form1.Label2.Caption:=DateiName;
       writeln(Datei,DatumUhrzeitString+'OK!');
       Closefile(Datei);
       i:=i+1;
     end
  else
     begin
       AssignFile(Datei,Pfad+'Daten/'+DateiName);
       Rewrite(Datei);
       Form1.Label1.Caption:=Pfad;
       Form1.Label2.Caption:=DateiName;
       writeln(Datei,DatumUhrzeitString+'OK!');
       Close(Datei);
 
     end;

end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form1.Label1.Caption:='';
  Form1.Label2.Caption:='';
  Form1.Timer1.Enabled:=True;
  i:=0;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Form1.Timer2.Enabled:=True;
end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin
  Messwerte_schreiben;
  Form1.Label3.Caption:=IntToStr(i);
end;

end.


Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Append bei Textdatei bringt error

Beitrag von Socke »

Dir ist schon klar, dass du vollkommenen Wirrwar mit deinen Dateinamen hast?
Versuch mal in FileExists und AssignFile den selben Dateinamen anzugeben. Dann sollte das passen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Append bei Textdatei bringt error

Beitrag von Winni »

Hi!

Nach dem FileExists solltest Du eigentlich kein try mehr benötigen - es sei denn, die Festplatte ist defekt.

Zweitens knallt es bei close(Datei). Das muss heißen:

Code: Alles auswählen


CloseFile(Datei);
Winni

Bergmensch
Beiträge: 13
Registriert: Do 6. Mai 2021, 18:16

Re: Append bei Textdatei bringt error

Beitrag von Bergmensch »

Socke hat geschrieben:
Fr 20. Aug 2021, 20:03
Dir ist schon klar, dass du vollkommenen Wirrwar mit deinen Dateinamen hast?
Versuch mal in FileExists und AssignFile den selben Dateinamen anzugeben. Dann sollte das passen.
Oje! Manchmal sieht man vor lauter Wald die Bäume nicht...
So funktioniert's!
VIELEN DANK FÜR DEINE HILFE!

Bergmensch
Beiträge: 13
Registriert: Do 6. Mai 2021, 18:16

Re: Append bei Textdatei bringt error

Beitrag von Bergmensch »

Winni hat geschrieben:
Fr 20. Aug 2021, 20:32
Hi!

Nach dem FileExists solltest Du eigentlich kein try mehr benötigen - es sei denn, die Festplatte ist defekt.

Zweitens knallt es bei close(Datei). Das muss heißen:

Code: Alles auswählen


CloseFile(Datei);
Winni
DANKE!

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Append bei Textdatei bringt error

Beitrag von fliegermichl »

Winni hat geschrieben:
Fr 20. Aug 2021, 20:32
Zweitens knallt es bei close(Datei). Das muss heißen:

Code: Alles auswählen


CloseFile(Datei);
Da bin ich ganz am Anfang auch drüber gestolpert weil in BP hieß das wirklich noch close(Datei);

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Append bei Textdatei bringt error

Beitrag von af0815 »

Das Close wurde im Laufe der Zeit mehrdeutig. Zuerst musste man angeben welches close aus welcher Unit verwendet werden soll, später wurde FileClose eingeführt um es eindeutig zu machen.

Man stolpert von Zeit zu Zeit darüber, weil alter Code und viele Beispiele noch Close alleine verwenden.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Append bei Textdatei bringt error

Beitrag von wp_xyz »

Hier konkret ist die Verwendung von Close() kein Problem, denn die Prozedur Messwerte_Schreiben(), in der es vorkommt, ist keine Methode des Formulars (wo das Close das Formular schließen würde), sondern eine einfache Prozedur. Bringe ich das Durcheinander mit den Pfad- und Dateinamen in Ordnung, läuft das Programm ohne weitere Änderung, also auch mit dem Close.

@Bergmensch: Ein Bemerkung zu deiner Art mit Methoden umzugehen. Deine TForm1.FormCreate-Methode ist:

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form1.Label1.Caption:='';
  Form1.Label2.Caption:='';
  Form1.Timer1.Enabled:=True;
  i:=0;
end;
Das funktioniert zwar, ist aber falsch, denn die Instanz-Variable der Klasse TForm1 kann irgendeinen Namen haben, nicht nur "Form1". Was passiert, wenn dir irgendwann diese automatisch generierten Variablennamen wie Form1 auf die Nerven gehen und du das Formular von "Form1" nach "HauptFormular" umbenennst? Oder du merkst, dass du ein zweites Formular derselben Klasse benötigst, das du dann "Form1a" nennst. Plötzlich wird dein Programm nicht mehr funktionieren, weil es die Variable "Form1" nicht mehr gibt. Das kannst du vermeiden, indem du konsequent das "Form1" in Methoden der Klasse TForm1 weglässt - das Formular "weiß" sowieso, dass das Label1 und Label2 und der Timer1 zu ihm gehören, oder wenn es zweideutig wird, setze ein "Self" davor, also "Self.Label1.Caption" statt "Form1.Label1.Caption".

Die Prozedur Messwerte_schreiben() ist auch so ein Ding, über das man nachdenken sollte. Denn es ist von Form1 abhängig, wobei die Abhängigkeit nur sichtbar wird, wenn man sich pingelig den Quelltext ansieht. Entweder machst du daraus eine Methode des Formulars (deklarierst es also innerhalb von TForm1), damit ist klar, dass die Prozedur vom Formular abhängt, und du kannst auch, wie oben schon gesagt, das "Form1." weglassen. Oder aber, genau besehen, hat das, was in der Prozedur passiert, nichts mit dem Formular zu tun, es passieren nur ein paar Ausgaben auf dem Formular. Das könntest du ermöglichen, indem die nötigen Strings als var-Parameter in der Messwerte_schreiben()-Prozedur bereitgestellt und vom aufrufenden Formular direkt verarbeitet werden:

Code: Alles auswählen

procedure Messwerte_schreiben(var Zaehler: Integer; var Pfad, Dateiname,Fehler: String);
var
  DatumUhrzeitString  :String;
  Datei               :Textfile;
begin
  DatumUhrzeitString:=FormatDateTime('yyyy.mm.dd hh:nn:ss', now);

  Fehler := '';
  DateiName:='Test.txt';
  Pfad:= ExtractFilePath(paramstr(0)) + 'Daten';

  if not DirectoryExists(Pfad) then
     ForceDirectories(Pfad);

  if FileExists(Pfad+DateiName) then
     begin
       AssignFile(Datei,Pfad+DateiName);
       try
         Append(Datei);
       except
         on E: EInOutError do
            Fehler := E.Message;
       end;
       writeln(Datei, DatumUhrzeitString+'OK!');
       Closefile(Datei);
       Zaehler := Zaehler+1;
     end
  else
     begin
       AssignFile(Datei,Pfad+DateiName);
       Rewrite(Datei);
       writeln(Datei,DatumUhrzeitString+'OK!');
       CloseFile(Datei);
     end;
end;        

procedure TForm1.Timer2Timer(Sender: TObject);
var
  pfad, dateiname, fehlerStr: String;
begin
  Messwerte_schreiben(i, pfad, dateiname, fehlerStr);
  Label1.Caption := pfad;
  Label2.Caption := dateiname;
  if fehler = '' then
    Label3.Caption:=IntToStr(i)
  else
    Label3.Caption := FehlerStr; 
end; 
  
Auf diese Art und Weise könntest du die Prozedur Messwerte_schreiben zum Beispiel in eine eigene Unit stecken, in der noch weitere Prozeduren stehen, die mit Messungen und ihrer Auswertung zu tun haben, und du hättest Programmlogik und Benutzeroberfläche sauber getrennt.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Append bei Textdatei bringt error

Beitrag von Winni »

Hallo!

Close auf einen Textfile gibt:

closetest1.pas(66,14) Error: Wrong number of parameters specified for call to "Close"

prinzipiel:

* Die "alte" Pascal-Definition und auch gültig in purem fpc:

Code: Alles auswählen

var: txt: Text; 
assign (txt,'WasWeissIch'); 
close (txt);
* Die Definition von Delphi und Lazarus, gültig seit Delphi 1:

Code: Alles auswählen

var  txt: Textfile;
assignFile (txt,'WasWeissIch');
closeFile (txt);
Nur um das nochmals klarzustellen.

Winni

Bergmensch
Beiträge: 13
Registriert: Do 6. Mai 2021, 18:16

Re: Append bei Textdatei bringt error

Beitrag von Bergmensch »

Hallo allerseits!
Vielen Dank für eure ergänzenden Infos!
Bin sehr froh über jeden Hinweis!
Schöne Grüße,
Bergmensch

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Append bei Textdatei bringt error

Beitrag von wp_xyz »

Winni hat geschrieben:
Sa 21. Aug 2021, 17:36
Close auf einen Textfile gibt:

closetest1.pas(66,14) Error: Wrong number of parameters specified for call to "Close"
Funktioniert bei mir einwandfrei:

Code: Alles auswählen

program Project1;
var
  TF: TextFile;
begin
  AssignFile(TF, 'test.txt');
  Rewrite(TF);
  WriteLn(TF, 'abc');
  Close(TF);
end. 
Oder rufst du das Close aus einem Formular eines LCL-Programms heraus auf? Klar, dann geht das nicht, denn Close (ohne Parameter) schließt das Formular. Genauso bei Assign (mit 1 Parameter), das bei TPersistent-Abkömmlingen die Properties kopiert.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Append bei Textdatei bringt error

Beitrag von Winni »

Hi!

Funktioniert nicht einwandfrei:

Code: Alles auswählen

test.pas(5,3) Error: Identifier not found "AssignFile
"

Wofür erklär ich das denn??? - siehe oben.

Winni

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Append bei Textdatei bringt error

Beitrag von wp_xyz »

Keine Ahnung, wie du deinen FPC verkonfiguriert hast. Ich habe jetzt auf Windows Laz-trunk/FPC 3.2.2 (32 bit), Laz 2.0.12/FPC3.2.0 (32 bit), Laz 2.08./FPC 3.2.0 (64 bit) Laz 1.6.4/FPC 2.6.4 (32-bit) und auf Ubuntu Laz-trunk/FPC 3.2.2 (64bit) getestet, jeweils Konfiguration "aus der Tüte", und jedes mal funktioniert es.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Append bei Textdatei bringt error

Beitrag von Winni »

Hi!

Da hast Du doch wieder etwas aus dem Menü "Neues Projekt" genommen, das irgenwelche Units einbindet, Ungefragt.

Ein echtes fpc-Programm macht man so:
Markiere Deinen obigen code.
Kopier den in Deinen Lieblings-Editor.
Speichern. Ich hab's closestest.pas genannt.
Dann :

Code: Alles auswählen

fpc closetest.pas
Dann passiert der Error.

Dass es bei Dir glatt durchgeht, darf nie und nimmer passieren.
Das bedeutet, dass irgendwo die LCL eingebunden ist.
Was eine Frechheit ist, wenn man ein pures Pascal-Programm haben möchte.

Assignfile ist in der lclproc definiert.

Oder Du hast irgendwo außerhalb des Sources den objfpc flag gesetzt - das gehört sich nicht.
Auf dem nächsten Rechner mit ne anderen fpc.cfg fällt man auf die Schnut.

Winni

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Append bei Textdatei bringt error

Beitrag von wp_xyz »

OK, wenn ich's so mache, dann kann ich deine Aussage bestätigen, genauso wenn ich das Programm in der IDE ausführe und den Mode auf {$MODE FPC} oder {$MODE TP} einstelle (*). Aber das war eigentlich nicht die Fragestellung, sondern es ging mir um das Problem des Fragestellers mit einem bestimmten Lazarus-Code, in dem explizit {$MODE ObjFPC} gesetzt ist und AssignFile und Code gemischt vorhanden sind.

Du hattest dazu ganz oben geantwortet: "knallt es bei close(Datei). Das muss heißen: CloseFile(Datei)". Ich selbst hätte zwar auch CloseFile genommen, aber strenggenommen ist die Verwendung von Close kein Problem, denn im {$MODE ObjFPC}, {$MODE Delphi}, {$MODE DelphiUnicode} vertragen sich Assign/Close/Text und AssignFile/CloseFile/TextFile miteinander, weil hier die Unit ObjPas dazugebunden wird, in der AssignFile/CloseFile/TextFile als Aliasse zu Assign/Close/Text aus der System-Unit definiert sind (mit der LCL hat das gar nichts zu tun):

Code: Alles auswählen

// aus objpas(h):
type
  TextFile = Text;

Procedure AssignFile(out t:Text;const Name:RawBytestring);
begin
  System.Assign (T,Name);
end; 

Procedure CloseFile(Var t:Text); [IOCheck];
begin
  System.Close(T);
end;
----
(*) In meinem vereinfachten Beispiel hätte ich {$MODE ObjFPC} angeben können, aber die IDE stellt das per default ein. Und wer denkt schon daran, dass jemand einen einfachen Texteditor der IDE vorzieht... (Ich weiß, es gibt Gründe dafür)

Antworten