Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi TFileStream - Datei bereits geöffnet ? (https://www.delphipraxis.net/114643-tfilestream-datei-bereits-geoeffnet.html)

slemke76 28. Mai 2008 19:05


TFileStream - Datei bereits geöffnet ?
 
Hallo zusammen,

folgender Source:

Delphi-Quellcode:
    Stream := TFileStream.Create(XMLFile, fmCreate or fmOpenWrite);
    DomToXmlParser1.WriteToStream(FDoc, 'UTF-8', Stream);
    // auch schon getestet : CloseHandle(Stream.Handle);
    Stream.Free;
Dieses Stück Code steht an einer Stelle, die mehrere Male pro Minute durchlaufen wird.
Das Problem ist nun, dass nach einer gewissen Zeit (immer unterschiedlich) das Programm stoppt und sagt, dass die Datei <xmlfile> nicht geöffnet werden könne, weil ein anderer Prozess darauf zugreift.
Ich habe jetzt das ganze erstmal in ein try...finally verpackt, aber das löst ja nicht das zugrunde liegende Problem. Ein CloseHandle habe ich auch schonmal probiert.

Hat jemand eine Idee ? Ich kann die Datei auch leider nicht geöffnet lassen (geht einfach nicht...).

lg
Sebastian

[edit=SirThornberry]"Problem" aus Titel entfernt - Mfg, SirThornberry[/edit]

Die Muhkuh 28. Mai 2008 19:08

Re: TFileStream Problem
 
Zitat:

Zitat von slemke76
Ich kann die Datei auch leider nicht geöffnet lassen (geht einfach nicht...).

Warum?

slemke76 28. Mai 2008 19:16

Re: TFileStream Problem
 
Hi !

unmöglich ist gar nichts; aber der Aufwand ist extrem hoch.
Ausserdem geht es mir auch ein wenig darum, das Problem zu verstehen. Wenn ich ein Closehandle und/oder Free mache, dann gehe ich doch davon aus, dass die Datei auch genauso gespeichert ist. Selbst wenn ein Cache dazwischen ist, müsste die nächste Lese-Anfrage ja auf den Cache bedient werden und da ist die Datei ja zu...

lg
Sebastian

SirThornberry 28. Mai 2008 19:17

Re: TFileStream Problem
 
@slemke76: Könntest du deinem Beitrag bitte einen aussagekräftigen Titel geben?

slemke76 28. Mai 2008 19:18

Re: TFileStream Problem
 
Zitat:

Zitat von SirThornberry
@slemke76: Könntest du deinem Beitrag bitte einen aussagekräftigen Titel geben?

ok so ?

lg

Die Muhkuh 28. Mai 2008 19:20

Re: TFileStream Problem
 
Zitat:

Zitat von slemke76
Zitat:

Zitat von SirThornberry
@slemke76: Könntest du deinem Beitrag bitte einen aussagekräftigen Titel geben?

ok so ?

lg

Jupp :zwinker:

slemke76 28. Mai 2008 19:28

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Hi!

Dann also zurück zum Thema :-) Hat jemand eine Idee ?

lg
Sebastian

DeddyH 28. Mai 2008 19:33

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Hier im Forum suchenIsFileInUse

Die Muhkuh 28. Mai 2008 19:34

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Hi,

Du könntest mal noch den Modus "fmShareDenyNone" verwenden:

Zitat:

Zitat von Delphi-Hilfe
fmShareDenyNone
Andere Anwendungen können die Datei ohne Einschränkungen zum Lesen oder Schreiben öffnen.


littleDave 28. Mai 2008 19:42

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Ich glaube sogar, dass das:
Delphi-Quellcode:
fmCreate or fmOpenWrite
Probleme machen kann. Ich würd das als erstes mit einer if-Abfrage lösen:
Delphi-Quellcode:
if FileExists(XMLFile) then
  Stream := TFileStream.Create(XMLFile, fmOpenWrite)
else
  Stream := TFileStream.Create(XMLFile, fmCreate);
Ist nur so eine Vermutung von mir, dass fmCreate zusammen mit fmOpenWrite Probleme machen könnte - ist aber reine Spekulation.

slemke76 28. Mai 2008 19:46

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Hi !

@DeddyH:
Ist ein guter Tip, damit könnte ich alternativ zu TFileStream die Fehler umschiffen; ich probiers.

@Die Muhkuh:
Könnten dann nicht die vermeintlich neueren Daten durch ältere überschrieben werden ?
Die besagte Datei wird *definitiv* nur durch die Anwendung in meinem Fehlerfall geöffnet und geschlossen. Wenn die Datei nun noch offen ist (wie er behauptet), dann muss das ja vom letzten Durchlauf kommen !? Wenn ich dann fmShareDenyNone verwende, könnte es dann passieren, dass der nächste Durchlauf mit den Daten des vorherigen überschrieben wird ?

@littleDave:
Die Datei muss jedes mal neu erstellt werden, aber ich weiss gar nicht, warum ich dann so einen Blödsinn da drin stehen habe; ich probiers aus !

@all: Es handelt sich i.ü. um einen W2k3 Server.

Ich suche eigentlich soetwas wie ein .Flush oder auch das Closehandle - eben so, dass ich sicher sein kann, dass die Daten wirklich geschrieben sind...


lg

Die Muhkuh 28. Mai 2008 19:49

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Hi,

Du könntest eine bool'sche Variable setzen, wenn die Datei offen ist. Wenn diese dann true ist, schreibst Du einfach nicht.

Warum müssen die Daten eig. pro Minute ein paar mal geschrieben werden?

Neutral General 28. Mai 2008 19:49

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Hi,

Probierst mal nur mit fmCreate ohne fmOpenWrite. Das müsste funktionieren... Und geschrieben werden die Daten spätestens wenn du Free aufrufst.

Gruß
Neutral General

slemke76 28. Mai 2008 20:22

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Hi,

@Neutral General:
Habe ich probiert; gleiches Problem :-( :
Stream := TFileStream.Create(XMLFile, fmCreate);
Somit dürfte auch die vorgeschlagene Fallunterscheidung nicht gehen....

@Die Muhkuh:
Wenn ich eine Boolsche Variable setze, habe ich so nichts davon; vom Ablauf her ist sicher gestellt, dass es keine Überlappungen gibt - der Timer, der die Funktion aufruft ist bis nach abarbeitung auf false und wird erst dann wieder gestartet.

Test mit IsFileInUse läuft, aber wie gesagt, das wäre ja nur ein "umgehen".

lg
Sebastian

littleDave 28. Mai 2008 20:30

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Zitat:

Zitat von slemke76
[...] Die Datei muss jedes mal neu erstellt werden [...]

Wie schauts den damit aus? Hast du schon geschaut, ob DeleteFile nicht manchmal fehl schlägt und warum? Ich glaub, dass wäre noch eine sinnvolle Stelle, an der du suchen kannst.

Muetze1 28. Mai 2008 20:30

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Zitat:

Zitat von slemke76
@Die Muhkuh:
Wenn ich eine Boolsche Variable setze, habe ich so nichts davon; vom Ablauf her ist sicher gestellt, dass es keine Überlappungen gibt - der Timer, der die Funktion aufruft ist bis nach abarbeitung auf false und wird erst dann wieder gestartet.

Aber genau dies scheint trotzdem das Problem zu sein, denn anders lässt sich der Fehler nicht erklären. Somit: probier dies mal mit der boolschen Variablen aus.

slemke76 28. Mai 2008 20:31

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Nochmal ich :-)

Das Problem ist im übrigen nicht neu:
http://groups.google.com/group/de.co...73bc0?lnk=raot

Ich habe ausserdem gelesen, das TStream von Delphi gepuffert ist.

Ich werde es jetzt auch nochmal mit
FlushFileBuffers(Stream.Handle) probieren.

lg

Neutral General 28. Mai 2008 20:32

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Hi,

Ansonsten versuch es mal mit meinem TFileStreamEx aus meiner MappedStreams.pas *Werbung mach* :mrgreen:

In den nächsten Tagen wird allerdings eine neue Version hochgeladen.

Gruß
Neutral General

slemke76 28. Mai 2008 20:38

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Hi,

@Neutral General:
bin ich vor 5 Minuten beim Googlen drauf gestossen. Das werde ich als letztes Ass im Ärmel behalten (als vorletztes - das letze wäre, das ganze mal mit fopen zu probieren :-) ).

@all:
Ich habe zum testen die Boolsche Variable jetzt mal gesetzt:

Delphi-Quellcode:
if (MainForm.testbool) then ShowMessage('FEHLER!');
MainForm.testbool:=true;
    Stream := TFileStream.Create(MainForm.AppDataDirConfig +  '\MicoData.xml', fmCreate);
    DomToXmlParser1.WriteToStream(FDoc, 'UTF-8', Stream);
    FlushFileBuffers(Stream.Handle);
    Stream.Free;
MainForm.testbool:=false;
lg

slemke76 29. Mai 2008 07:58

Re: TFileStream - Datei bereits geöffnet ?
 
Guten Morgen,

@Muetze1: Das Programm ist wieder abgestürzt und das "ShowMessage('FEHLER')" ist nicht ausgelöst worden; ausserdem habe ich nochmals alle Stellen des Sources geprüft; die Datei wird nur an der einen Stelle aufgemacht/geschrieben.

Es scheint also ein Problem von TFileStream zu sein...

Für heute morgen habe ich erstmal ein "if IsFileInUse" eingesetzt; zu mehr ist heute keine Zeit :cry:

lg

Codewalker 29. Mai 2008 08:03

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Zitat:

Zitat von littleDave
Ich glaube sogar, dass das:
Delphi-Quellcode:
fmCreate or fmOpenWrite
Probleme machen kann.

Probleme eigentlich nicht. Laut Delphi-Hilfe erstellt fmCreate eine Datei und wenn diese bereits vorhanden ist wird sie mit Schreibzugriff geöffnet.

Muetze1 29. Mai 2008 11:01

Re: TFileStream - Datei bereits geöffnet ?
 
@CodeWalker: Doch die Stelle ist soweit falsch, weil fmCreate eine vorhandene Datei überschreibt während fmOpenReadWrite die Datei nur öffnet aber ihren Inhalt bestehen lässt. Somit ist hier das Verhalten komplett gegensätzlich, deshalb können nicht beide angegeben werden. Aber das es zu keinen Problemen kommt wenn doch, liegt an der Implementierung von FileOpen() der VCL, welche nur auf fmCreate und nur in diesem Falle das richtige Flag an CreateFile() gibt -> es ignoriert das fmOpenReadWrite damit komplett, so lange fmCreate angegeben ist.

slemke76 15. Jun 2008 15:23

Re: TFileStream - Datei bereits geöffnet ?
 
Hallo,

ich wieder 8)

Also mit IsFileInUse hat es mehrere Tage gebraucht, aber es ist wieder "hängen" geblieben - ich könnte jetzt ein try...except...end drumherum bauen, aber ich würde schon gerne wissen, woher das Problem kommt.

Was ich jetzt noch probiert habe, ist mit Delphi 2007 statt Delphi 7 zu compilieren.

Hat aber auch nicht geklappt.

Jetzt werde ich die MappedStreams ausprobieren.

lg
Sebastian

himitsu 15. Jun 2008 15:56

Re: TFileStream Problem - Datei bereits geöffnet ?
 
Zitat:

Zitat von slemke76
Ich habe ausserdem gelesen, das TStream von Delphi gepuffert ist.

erstmal ist TStream abstract und da es aus diesem Grund erstmal garnichts ließt/schreibt, wird auch nichts gepuffert.

TFileStream(THandleStream) puffern selber nichts und die WindowsPufferung sollte bei diesem Problem keinen Einfluß haben, da sie vom Programm aus keinen Einfluß hat ... also wird FlushFileBuffers(Stream.Handle) nichts bewirken.


man müßte also erstmal rausbekommen welches Programm die Datei noch geöffnet hat (könntest ja z.B. mal mit einen Bei Google suchenUnlocker, oder 'nem Bei Google suchenProcess Explorer selber nachsehn, wer das ist),

oder wenn es an deinem Programm liegt: warum/wo die Datei nicht mehr geschlossen/freigegeben wird.


PS: wenn die Datei noch geöffnet ist, dann bring es auch nichts, wenn du eine andere Komponente verwendest, um auf diese Datei zuzugreifen ... gesperrt ist gesperrt.
(abgesehn die Komponente ist defekt und der Fehler kommt von ihr ... aber TFileStream selber sollte diesen Fehler nicht verursachen)

slemke76 15. Jun 2008 17:15

Re: TFileStream - Datei bereits geöffnet ?
 
Hallo zusammen,

ich habe jetzt mal die Routine in ein einigenes Programm gekapselt; das Problem trat immer noch auf. Ich habe daraufhin mal ein wenig herumgespielt und es hat sich herausgestellt, dass die Kombination (oder nur der AV) Virenscanner und Betriebssystem das Problem verursacht haben:

Vista mit Kaspersky Antivirus 2009: keine Probleme
W2K3 SBS mit Kaspersky für Windows Servers 6.x: Nach kurzer Zeit Absturz, da die Datei in Benutzung sei.

Die Routine sieht so aus:

Delphi-Quellcode:
procedure TForm1.btnStartClick(Sender: TObject);
begin
  btnStart.Enabled:=false;
  btnStart.Caption:='running...';
  Timer1.Enabled:=true;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Memo1.Lines.Add('rein');
  Timer1.Enabled:=false;
  DoSave();
  Timer1.Enabled:=true;
  Memo1.Lines.Add('raus');
end;
Delphi-Quellcode:
procedure DoSave();
var Stream: TFileStream;
    XMLFile: String;
    DomToXmlParser1: TDomToXmlParser;
    DomImplementation1: TDomImplementation;
    FDoc: TDOMDocument;
    FNodeElement: TDomElement;

begin
  XMLFile:='test.xml';
  // ----- XML-Zeugs -----
  DomImplementation1:=TDomImplementation.Create(nil);
  FDoc := TDomDocument.Create(DomImplementation1);
  DomToXmlParser1:=TDomToXmlParser.Create(nil);
  DomToXmlParser1.DOMImpl:=DomImplementation1;

  // --- XML root für Schnittstelle anlegen ---
  FNodeElement:=TDomElement.Create(FDoc, 'TEST');
  FDoc.AppendChild(FNodeElement);

  Stream := TFileStream.Create(XMLFile, fmCreate);
  DomToXmlParser1.WriteToStream(FDoc, 'UTF-8', Stream);
  Stream.Free;

  FNodeElement.Free;
  DomToXmlParser1.Free;
  FDoc.Free;
  DomImplementation1.Free;
end;
lg
Sebastian

himitsu 16. Jun 2008 09:20

Re: TFileStream - Datei bereits geöffnet ?
 
also könnte es so aussehn, als wenn der Virenscanner die Datei noch geöffnet hat. :stupid:

abgesehn, daß zur Sicherheit in DoSave in paar Try-Except/Finally nicht schaden könnten, damit bei einem/dem Fehler nicht vergessen wird etwas freizugeben ... vorallem die Datei zu schließen. :zwinker:

PS: wenn der Code mehrmals die Minute aufgerufen wird, warum öffnest du diese Datei dann ständig neu?
könnte sie denn nicht einmal geöffnet und die ganze Zeit über offen gelassen werden?

Da IsFileInUse scheinbar nichts bringt, da zwischen diesem und TFileStream.Create die Datei immernoch gesperrt werden kann (bzw. was anscheind auch schon passiert ist):
Delphi-Quellcode:
procedure DoSave();
var Stream: TFileStream;
    XMLFile: String;
    DomToXmlParser1: TDomToXmlParser;
    DomImplementation1: TDomImplementation;
    FDoc: TDOMDocument;
    FNodeElement: TDomElement;
    B: Boolean;

begin
  XMLFile:='test.xml';
  // ----- XML-Zeugs -----
  DomImplementation1:=TDomImplementation.Create(nil);
  FDoc := TDomDocument.Create(DomImplementation1);
  DomToXmlParser1:=TDomToXmlParser.Create(nil);
  DomToXmlParser1.DOMImpl:=DomImplementation1;

  // --- XML root für Schnittstelle anlegen ---
  FNodeElement:=TDomElement.Create(FDoc, 'TEST');
  FDoc.AppendChild(FNodeElement);


  B := False;
  repeat
    try
      Stream := TFileStream.Create(XMLFile, fmCreate);
      B := True;
    except
      Sleep(0);
    end;
  until B;
  try
    DomToXmlParser1.WriteToStream(FDoc, 'UTF-8', Stream);
  finally
    Stream.Free;
  end;

  FNodeElement.Free;
  DomToXmlParser1.Free;
  FDoc.Free;
  DomImplementation1.Free;
end;
OK, es ist nicht wirklich optimal und vorallem ein Except ohne Fehlerbehandlung wird nicht grad gern gesehn, aber was soll's :roll:
(zusetzlich noch ein (paar) Try-Finally für das ganze XML-Zeugs könnten dennoch nicht Schaden)

slemke76 17. Jun 2008 11:38

Re: TFileStream - Datei bereits geöffnet ?
 
Hi !

Der Code ist wirklich gut; ich habe es jetzt im Moment anders gelöst, aber das wird nochmal angepasst. Danke für den Input.
try-except für XML ist nicht wirklich notwendig - die Routinen laufen absolut problemlos; praktisch gesehen gibt es da nix, was abstürzt :-)

lg
Sebastian

himitsu 19. Jun 2008 12:38

Re: TFileStream - Datei bereits geöffnet ?
 
Zitat:

Zitat von slemke76
try-except für XML ist nicht wirklich notwendig - die Routinen laufen absolut problemlos; praktisch gesehen gibt es da nix, was abstürzt :-)

Na dann ist ja gut ... bin' halt nur gewohnt, daß zuviele DelphiObjekte mit Exceptions nur so um sich werfen :shock:

Aber wenn das so ist, dann sollte es ja reichen, wenn in der Schleife das Try-Except und "B" wegkommt und stattdessen einfach der Wert von "Stream" geprüft wird. (war mir aber fast sicher, daß der Konstruktor im Fehlerfall eine exception wirft :gruebel: )

grad nachgesehn ... wenn die datei nicht geöffnet wird, dann wird mit EFCreateError geworfen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:46 Uhr.

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