Append bei Textdatei bringt error

Für allgemeine Fragen zur Programmierung, welche nicht! direkt mit Lazarus zu tun haben.
Benutzeravatar
Jim Knopf
Beiträge: 98
Registriert: So 18. Mai 2014, 15:16
OS, Lazarus, FPC: Win10
CPU-Target: 64Bit
Wohnort: Klagenfurt
Kontaktdaten:

Re: Append bei Textdatei bringt error

Beitrag von Jim Knopf »

Ist das eine Multiuseranwendung?

Wenn nein, wäre dann nicht eine simple TStringList viel einfacher?

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 Bergmensch1

Ich hab Deinen Code mal grundlegend aufgeräumt.

Fangn wir mit den Fehlern an.

Falsch und gefährlich:

Code: Alles auswählen

Procedure TForm1.xyz;
begin
Form1.Komponente .....;
end;
Niemals die Variable Form1 in der Klassendefinition von TForm1 aufrufen.
Weil:

Nun gibt es irgenwo eine zweite Form namens KarlHeinz als Instanzvon TForm1. Möglicherweise in einer ganz anderen Unit.
Und dort ist Form1 evtl. undefiniert. Und nun? So etwas ist erstens falsch und führt zweiten zu schwer lokalisierbaren Fehlern.

Immer so

Code: Alles auswählen

Procedure TForm1.xyz;
begin
Komponente .....;
end;
Die Timer: Du benötigst den einen Timer nur, um den anderen zu starten.
Das liegt nun in Formcreate.

Die ganze Arie mit Datei, Pfad und fileExists wird so gekürzt:

Paramstr(0) war gestern. Den absoluten Pfad der exe-Datei erhält man mit Application.Location
Es verkürzt sich auft

Code: Alles auswählen

Dateiname := Application.Location+'Test.txt';
Der Pfad entfällt.

Den Test auf die Existenz der Datei muss man auch nur am Anfang machen, weil Deine Anwendung offensichtlich single user ist, also Dir niemand im Betrieb die Datei löscht.

Also tested Formcreate die Existenz und erzeugt im Zweifelsfall eine neue Datei.
Dann muss nie wieder getested werden.

Project anbei.

Grüße
Winni
Dateianhänge
Messwerte.zip
(127.14 KiB) 85-mal heruntergeladen

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Append bei Textdatei bringt error

Beitrag von PascalDragon »

Winni hat geschrieben:
Fr 20. Aug 2021, 20:32
Nach dem FileExists solltest Du eigentlich kein try mehr benötigen - es sei denn, die Festplatte ist defekt.
Man sollte bei sowas wie Append (oder auch Rewrite bzw. Reset) immer auf Fehler abprüfen, da zum Beispiel keine passenden Berechtigungen existieren könnten (was FileExists ja nicht überprüft) oder zufällig der Scheduler des Betriebssystem deinen Thread zwischen FileExists und Append schlafen gelegt und ein anderer Thread (eventuell auch einer anderen Anwendung) in der Zwischenzeit diese Datei angelegt hat (das ist natürlich bei manchen Dateien wahrscheinlicher als bei anderen, aber man sollte diesen Fall nicht unterschätzen).
Winni hat geschrieben:
So 22. Aug 2021, 01:27
Assignfile ist in der lclproc definiert.
Falsch. Die AssignFile-overloads sind in der Unit ObjPas deklariert, welche automatisch bei Verwendung von Modi wie ObjFPC oder Delphi verwendet wird.
FPC Compiler Entwickler

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 »

PascalDragon hat geschrieben:
Do 26. Aug 2021, 16:09

Man sollte bei sowas wie Append (oder auch Rewrite bzw. Reset) immer auf Fehler abprüfen, da zum Beispiel keine passenden Berechtigungen existieren könnten (was FileExists ja nicht überprüft) oder zufällig der Scheduler des Betriebssystem deinen Thread zwischen FileExists und Append schlafen gelegt und ein anderer Thread (eventuell auch einer anderen Anwendung) in der Zwischenzeit diese Datei angelegt hat (das ist natürlich bei manchen Dateien wahrscheinlicher als bei anderen, aber man sollte diesen Fall nicht unterschätzen).
Na, das ist aber arg konstruiert. Ist mir in über 40 Jahren Pascal nicht ein einzige Mal passiert.

Winni

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 »

Winni hat geschrieben:
Do 26. Aug 2021, 19:12
Na, das ist aber arg konstruiert. Ist mir in über 40 Jahren Pascal nicht ein einzige Mal passiert.
Sobald du mit anderen Programmen über Dateien interagieren möchtest, ist das tatsächlich ganz normal.
Solltest du in deinem Programm nur spezifische Dateien bearbeiten, kommt das in der Tat eher selten vor.
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 »

Socke hat geschrieben:
Do 26. Aug 2021, 21:32
Sobald du mit anderen Programmen über Dateien interagieren möchtest, ist das tatsächlich ganz normal.
Solltest du in deinem Programm nur spezifische Dateien bearbeiten, kommt das in der Tat eher selten vor.
Hi!

Programm A schreibt in Datei X.
Programm B liest Datei X

Programm B schreibt in Datei Y
Programm A liest Datei Y

Brauchst Du nicht mal Semaphore oder sonstwas.
Brauchst auch kein fileExists.
Musst Du nur pollen ob die Dateigröße sich verändert hat.

Geht astrein mit Linux-Dateisystem.
Gibt aber Probleme in Windows.

Winni

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Append bei Textdatei bringt error

Beitrag von PascalDragon »

Winni hat geschrieben:
Do 26. Aug 2021, 19:12
PascalDragon hat geschrieben:
Do 26. Aug 2021, 16:09

Man sollte bei sowas wie Append (oder auch Rewrite bzw. Reset) immer auf Fehler abprüfen, da zum Beispiel keine passenden Berechtigungen existieren könnten (was FileExists ja nicht überprüft) oder zufällig der Scheduler des Betriebssystem deinen Thread zwischen FileExists und Append schlafen gelegt und ein anderer Thread (eventuell auch einer anderen Anwendung) in der Zwischenzeit diese Datei angelegt hat (das ist natürlich bei manchen Dateien wahrscheinlicher als bei anderen, aber man sollte diesen Fall nicht unterschätzen).
Na, das ist aber arg konstruiert. Ist mir in über 40 Jahren Pascal nicht ein einzige Mal passiert.
Da ist nichts dran konstruiert, das basiert auf Fällen, die mir so bereits passiert sind und das unabhängig von Pascal (da dies kein Problem der Sprache ist).
Winni hat geschrieben:
Do 26. Aug 2021, 23:21
Socke hat geschrieben:
Do 26. Aug 2021, 21:32
Sobald du mit anderen Programmen über Dateien interagieren möchtest, ist das tatsächlich ganz normal.
Solltest du in deinem Programm nur spezifische Dateien bearbeiten, kommt das in der Tat eher selten vor.
Hi!

Programm A schreibt in Datei X.
Programm B liest Datei X

Programm B schreibt in Datei Y
Programm A liest Datei Y

Brauchst Du nicht mal Semaphore oder sonstwas.
Brauchst auch kein fileExists.
Musst Du nur pollen ob die Dateigröße sich verändert hat.
Aber das ist ein anderer Usecase als

Programm A prüft, ob Datei X bereits existiert
Programm A legt Datei X an, falls nicht
Programm B prüft, ob Datei X bereits existiert
Programm B legt Datei X an, falls nicht

Da kann nämlich je nach Scheduling auch das folgende bei rauskommen:

Programm A prüft, ob Datei X bereits existiert
Programm B prüft, ob Datei X bereits existiert
Programm B legt Datei X an, falls nicht
Programm A legt Datei X an, falls nicht (und hier knallt's dann)
Winni hat geschrieben:
Do 26. Aug 2021, 23:21
Geht astrein mit Linux-Dateisystem.
Gibt aber Probleme in Windows.
Das hat nichts mit Dateisystem zu tun (ein Ext3 unter Windows würde sich genauso wie ein NTFS unter Windows verhalten, genauso wie sich ein NTFS unter Linux genauso wie ein Ext3 verhält), sondern damit, dass Linux "Advisory File Locking" und Windows "Mandatory File Locking" verwendet und sich mit letzterem exklusiver Zugriff auch tatsächlich durchsetzen lässt.
FPC Compiler Entwickler

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!

Natürlich hat das was mit dem Dateisystem zu tun.

NTFS schreibt die Dateigröße erst nach einem close(file) auf die Platte.

ext2/3/4 schreibt bei jedem Schreibzugriff die aktuelle Größe auf die Platte.

Winni

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 »

Winni hat geschrieben:
Fr 27. Aug 2021, 13:21
Natürlich hat das was mit dem Dateisystem zu tun.

NTFS schreibt die Dateigröße erst nach einem close(file) auf die Platte.
Wobei die Dateigröße in PascalDragons Beispiel vollkommen egal ist. Da hat nur ein CreateFile Aufruf aber noch kein Write-Aufruf stattgefunden.
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 »

Socke hat geschrieben:
Fr 27. Aug 2021, 14:44
Winni hat geschrieben:
Fr 27. Aug 2021, 13:21
Natürlich hat das was mit dem Dateisystem zu tun.

NTFS schreibt die Dateigröße erst nach einem close(file) auf die Platte.
Wobei die Dateigröße in PascalDragons Beispiel vollkommen egal ist. Da hat nur ein CreateFile Aufruf aber noch kein Write-Aufruf stattgefunden.

Ich hab mich natürlich auf mein Beispiel bezogen.
Da spielt das sehr wohl eine Rolle.

Winni

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Append bei Textdatei bringt error

Beitrag von PascalDragon »

Winni hat geschrieben:
Fr 27. Aug 2021, 13:21
Natürlich hat das was mit dem Dateisystem zu tun.

NTFS schreibt die Dateigröße erst nach einem close(file) auf die Platte.

ext2/3/4 schreibt bei jedem Schreibzugriff die aktuelle Größe auf die Platte.
Nein, das hat nichts mit dem Dateisystem zu tun. Es hat damit zu tun, wie das Betriebssystem mit dem Dateisystem arbeitet. Und das hängt komplett von der Kombination aus Betriebssystem und Dateisystem ab. Und wenn deine Aussage bzgl. NTFS stimmen würde, dann könnte man offen gehaltenen Dateien auf einem NTFS unter Windows nicht beim wachsen zusehen, was man nämlich kann.
FPC Compiler Entwickler

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 »

PascalDragon hat geschrieben:
Sa 28. Aug 2021, 12:01
[Und wenn deine Aussage bzgl. NTFS stimmen würde, dann könnte man offen gehaltenen Dateien auf einem NTFS unter Windows nicht beim wachsen zusehen, was man nämlich kann.
Stimmt nicht unter Win7/64. Dateigröße bleibt Null bis zum close(file).

Winni

Benutzeravatar
kralle
Lazarusforum e. V.
Beiträge: 988
Registriert: Mi 17. Mär 2010, 14:50
OS, Lazarus, FPC: Linux Mint 20 , FPC 3.3.1 , Lazarus 2.1.0 -Win10 & XE7Pro
CPU-Target: 64Bit
Wohnort: Bremerhaven
Kontaktdaten:

Re: Append bei Textdatei bringt error

Beitrag von kralle »

Ihr driftet ab und werdet rauer im Ton.
Bitte nicht ...

Gruß Heiko
OS: Manjaro Linux, Debian und Windows 10
FPC-Version: 3.2.2 , Lazarus 3.0
+ Delphi XE7SP1

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!

????

Wir werden nicht rauer.

Und über die rauen Fakten: Beschwer dich bei NTFS.

Winni

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 »

Winni hat geschrieben:
Sa 28. Aug 2021, 13:04
Stimmt nicht unter Win7/64. Dateigröße bleibt Null bis zum close(file).
Was auch nicht ganz richtig ist. Die Dateigröße wird mit jeder Änderung aktualisiert. Der Verzeichniseintrag wird aber nur bei einem Close aktualisiert.
Sehr schön beschrieben ist dies im Blog

Code: Alles auswählen

Why is the file size reported incorrectly for files that are still being written to?
- was natürlich nur für Windows gilt. Andere NTFS-Treiber können sich hier anders verhalten.

Ein Detail aus dem Blog von 2011 stimmt nicht mehr ganz für Windows 10. Der Explorer kann durchaus die tatsächliche Dateigröße aktualisieren, wenn man auf "Aktualisieren" klick. Dazu scheint er wohl wie im Blogbeitrag beschrieben die Datei zu öffnen und zu schließen, da sich dies auch auf ein FindFirst() im laufenden Programm auswirkt. Ein automatisches Update erhält er tatsächlich erst mit dem Schließen der Datei.

Mit einem kleinen Programm kann man das ganz einfach untersuchen.

Code: Alles auswählen

program project1;

{$Mode objfpc}{$H+}

uses
  Windows, sysutils, classes;

// Die Testdatei
const
  FILENAME = 'myfile';

// ermittelt die Dateigröße per FindFirst
function GetEnumeratedSize: Qword;
var
  srcrec: TRawByteSearchRec;
begin
  if FindFirst(FILENAME, faAnyFile, srcrec) = 0 then
  begin
    Result := srcrec.Size;
    FindClose(srcrec);
  end;
end;

var
  f: TFileStream;
  Buffer: Array[0..999] of Byte; // ein Puffer, der in die Datei geschrieben wird
  c: String = #0;
  fsize: Int64Rec;
begin    
  WriteLn('Enumerated Size: ', GetEnumeratedSize);

  f := TFileStream.Create(FILENAME, fmCreate);
  try
    repeat
      case c of
        #10, #13: continue;
        'c', 'C': begin
          f.Write(Buffer[0], Length(Buffer));
          WriteLn('Stream Size: ', f.Size);
          fsize.Lo := GetFileSize(f.Handle, @fsize.Hi);
          WriteLn('Windows File Size: ', Int64(fsize));
          WriteLn('Enumerated Size: ', GetEnumeratedSize);
        end;
      end;

      ReadLn(c);
    until c[1] in ['x', 'X'];
  finally
    FreeAndNil(f);
  end;

  WriteLn('Enumerated Size: ', GetEnumeratedSize);
  ReadLn;
end.
Conclusio: Es bleibt kompliziert.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten