![]() |
Simultaner Zugriff auf Datei
Hallo zusammen,
ich programmiere erst seit kurzem mit Delphi und habe ein Problem, was ich bisher nicht im Netz, in Foren oder sonstigem beschrieben gefunden habe. (Und dennoch scheint es mir ein häufig vorkommendes Problem zu sein ;)) Das Problem: ich habe zwei Programme, die beide auf eine Datei zugreifen sollen (das eine schreibt Daten hinein, das andere liest diese). Das ganze geschieht zyklisch, aber nicht in festen Zeitabständen, sodass das Lese-Programm (welches ich nur beeinflussen kann) alle X-Millisekunden den Zeitstempel der Datei auf eine Aktualisierung überprüft und dann mit dem Auslesen beginnen würde. Bei der Abfrage des Zeitstempels kann/kommt es z.T. zu gleichzeitigem Zugriff beider Programme auf die Datei, was zum Programmabsturz führt. Ich hatte versucht, das Lesen des Zeitstempels über try...except abzufangen, funktioniert aber nicht. Gibt es in Delphi andere Möglichkeiten, dieses Problem zu umgehen, ohne beide Programme von außen schedulen zu müssen?? Mir würde es zudem genügen, wenn sich das Lese-Programm "devot" verhält, d.h. seinen Zugriff auf die Datei nicht einfordert, sondern einfach wartet, bis das Schreibe-Programm fertig ist. Vielen Dank schon einmal! |
AW: Simultaner Zugriff auf Datei
Rewrite öffnet die Datei exclusiv. Währenddessen in eine zweites Rewrite nicht möglich. (Nur) das muß man abfangen, dem Reset ist es egal.
|
AW: Simultaner Zugriff auf Datei
Grundsätzlich können alle Rechte gewehrt/gesperrt werden.
Beim Zugriff auf eine Datei muß man angeben was man für Recht haben muß (Lesen und/oder Schreiben) und dabei kann man auch angeben welche weiteren Zugriffe gleichzeitig erlaubt sind, egal ob von fremden Programmen oder vom Eigenem. Ist die Datei bereits geöffnet, dann muß der gewünschte Zugriff vom Anderen erlaubt sein. Die alten Dateifunktionen gewähren nur gleichzeitige Lesezugriffe und es gibt keine (praktikable) Möglichkeit das zu beeinflussen. Vom RTL-Code her sah es jetzt zwar so aus, als wenn immer Lesezugriffe gewehrt weren, aber beim Schreiben verbiete ich (standardmäßig) selber auch fast immer alle weiteren Zugriffe und beim Lesen verbiete ich Anderen das Schreiben, um konsistente Daten zu gewährleisten. Also wenn das die RTL doch genauso macht und ich es jetzt nur falsch sah, dann würde ich das Verhalten dennoch als richtig betrachten. Fazit: Dein Programm muß die Zugriffe des anderen Programms gewährleisten und theoretisch könntest du die Datei sogar die ganze Zeit offen lassen. Aber wenn das andere Programm deine Zugriffe beim Lesen verbietet, dann wirst du damit leben müssen, da du das ja nicht beeinflussen kannst. |
AW: Simultaner Zugriff auf Datei
Danke Euch beiden, das hat schon mal Hilfe in die richtige Richtung gegeben. Was ich vergessen hatte zu erwähnen, ist dass die Schnittstellen Datei ein XML File ist, und "Rewrite", so schön einfach dieser Ansatz auch aussah, nach meiner Recherche nur bei Textfiles funktioniert?!
Aber ich denke, ich suche genau die Exklusivrechte beim Öffnen einer Datei, die Ihr angesprochen habt. Habe dazu ein kleines Beispiel programmiert, wobei mir diese Exclusivrechte sofort selber auf die Füße gefallen sind. Vlt seht ihr den Fehler.
Delphi-Quellcode:
// Beispiel XML erstellen
procedure TForm1.Button2Click(Sender: TObject); var root, c1: IXMLNode; begin count:=0; fn:='C:\Temp\Test.xml'; xml:=TXMLDocument.Create(self); xml.Active:=true; xml.Version:='1.0'; xml.Encoding:='UTF-8'; xml.StandAlone:='no'; root:=xml.AddChild('ErsterKnoten'); c1:=root.AddChild('ZweiterKnoten'); c1.Text:='1'; xml.XML.Text := FormatXMLData(xml.XML.Text); xml.Active:=true; xml.SaveToFile(fn); xml.Free; end; // Timer starten (weil später auch zyklischer Prozess) procedure TForm1.Button1Click(Sender: TObject); begin Timer1.Enabled:=true; end; procedure TForm1.Timer1Timer(Sender: TObject); begin inc(count); // Öffnen der zuvor erstellten Datei unter Exklusivrechten temp:=FileOpen(fn, fmOpenReadWrite or fmShareExclusive); if temp <> -1 then begin //hier soll die Datei jetzt bearbeitet werden xml:=TXMLDocument.Create(self); xml.LoadFromFile('C:\Temp\Test.xml'); xml.ChildNodes.Nodes[1].ChildNodes.Nodes[0].Text:=IntToStr(count); Label1.Caption:='Neuer Wert: '+IntToStr(count); xml.SaveToFile('C:\Temp\Test.xml'); xml.Free; temp FileClose(temp); end else begin Timer1.Enabled:=false; ShowMessage('Datei konnte nicht geladen werden'); end; end; end. Die Fehlermeldung lautet: Datei wird schon von einem anderen Prozess benutzt... Das Problem liegt wohl darin, dass ich mit LoadfromFile das XML nochmal versuche zu öffnen... aber wie sonst könnte man das XML anderweitig bearbeiten? Danke im Voraus! |
AW: Simultaner Zugriff auf Datei
Zitat:
Zitat:
Die Datei nicht exklusiv öffnen, den String auslesen und dann den XML-"String" an die XML-Komponente übergeben. Genauso kann man den XML-String erst aus der Komponente rausholen und dann selber in die Datei schreiben. |
AW: Simultaner Zugriff auf Datei
Zitat:
Und durch das Weglassen der Exklusivrechte können doch wieder andere Programme auf die Datei zugreifen, während dieses Programm am bearbeiten ist, oder? (Das wollte ich ja verhindern) |
AW: Simultaner Zugriff auf Datei
Entweder habe ich gravierende Wissenslücken oder, soweit wir hier fest bei Windows sind, macht keiner eine Datei zum Lesen auf wenn da grade reingeschrieben wird. Nicht einmal der gleiche Prozess.
Willst du die Datei ein weiteres mal (zum Lesen) aufmachen muss der Schreibende entweder ein Mapping für die Datei angelegt haben (siehe ![]() Ansonsten, kein Weg. Das hätte ich jetzt spontan behauptet. Wenn das nicht stimmt freue ich mich :wink: |
AW: Simultaner Zugriff auf Datei
Ich hab' mal ne Zeitlang das verwendet, dann aber wieder verworfen. Weiß aber nicht mehr warum?
Delphi-Quellcode:
function FileInUse(const FileName: string): boolean;
var Success: Cardinal; begin Result := false; if FileExists(FileName) then begin Success := CreateFile(PChar(FileName), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); Result := Success = INVALID_HANDLE_VALUE; if not Result then CloseHandle(Success); end; end; procedure Wait50; var ATime: Cardinal; begin ATime := GetTickCount; repeat until GetTickCount - ATime > 50; Application.ProcessMessages; end; function CanOpenFile(const FileName: string): boolean; var TryCount: integer; begin Result := true; if FileInUse(FileName) then begin TryCount := 0; repeat Wait50; Inc(TryCount); Result := not FileInUse(FileName); until Result or (TryCount = 20); end; if not Result then MessageDlg('Zugriff auf ' + FileName + ' verweigert.', mtError, [mbOK], 0); end; |
AW: Simultaner Zugriff auf Datei
Das versucht ja nur, mittels
Delphi-Quellcode:
die Datei zum Lesen aufzumachen und sagt, ob dabei
CreateFile
Delphi-Quellcode:
herauskam oder nicht. Auf so eine Lösung wird es denke ich ja auch hinauslaufen-
INVALID_HANDLE_VALUE
Nur würde ich hierbei bemängeln dass die Wahrscheinlichkeit zwar wahrscheinlich hoch, aber nicht garantiert ist dass du deine öffnen kannst nachdem das Prüfen einmal meinte, man könne sie zum Lesen öffnen: Zwischen Prüfen und Aufmachen kann sie sich ja schon wieder jemand anders geschnappt haben- Die Gegenseite könnte beispielsweise wieder anfangen zu schreiben. |
AW: Simultaner Zugriff auf Datei
Kann sein. Prüfte glaub ich GENERIC_READ or GENERIC_WRITE usw. Weiß nicht mehr so genau?
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:50 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