# gleichzeitiger Zugriff auf eine Textdatei



## muhazz (1. Mrz 2012)

Hallo!

Mir stellt sich folgendes Problem:

Ein mir nicht näher bekanntes Programm ("Programm1") aktualisiert ständig den Inhalt einer Textdatei, den ich mit einem weiteren Programm ("Programm2") auslesen soll.

Nun hatte ich die Vermutung, dass es bei gleichzeitigem Zugriff bzw. Änderung einer Datei Probleme geben kann und wurde durch eine kurze Recherche bestätigt.
Ich habe leider keine genauen Angaben darüber, auf welche Art die Textdatei durch Programm1 verändert wird, aber wie auch immer dieser Vorgang im Detail aussieht - ich denke mir, das Auslesen zu einem Zeitpunkt, wo eine Änderung begonnen aber nicht abgeschlossen wurde, wird zu falschen Ergebnissen führen, z.B. wenn der alte Inhalt gelöscht und noch kein neuer hinzugefügt wurde.

Bevor ich meine Ansätze für konkreten Lösungsvorschläge vorstelle, habe ich zuerst noch eine grundlegende Frage:
Wenn ich eine Datei test.txt durch

```
File f = new File("test.txt");
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader (fr);
```
öffne und diese danach (aber vor dem Schließen des Streams!) von außen geändert wird - wirkt sich das auf nachfolgende br.readLine() Aufrufe aus? Meine Vermutung: Bei FileReader-Objekten schon. Bei BufferedReader-Objekten allerdings wird der zu lesende Inhalt schon bei der Erzeugung des Readers in den Puffer geladen und ist deshalb "sicher" vor Veränderungen von außen. Allerdings weiß ich nicht, wie viel Text gepuffert wird - da die Textdatei klein ist und man die Puffergröße auch variieren kann, schätze ich, dass auch der gesamte Text gepuffert werden kann.
Im Folgenden gehe ich also davon aus, dass bei Änderungen der Datei während Auslesevorgängen mit einem BufferedReader-Objekt nichts schiefgeht.
[EDIT: Ach Mist. Während des Puffer-Vorgangs, der ja ein wiederholtes normales Einlesen ist, kann die Datei ja auch geändert werden. Mist.]


So, jetzt habe ich gelesen, dass Dateien "gelocked" werden können, um sie für eine bestimmte Zeit für bestimmte Zugriffe zu sperren. Wenn ich die vorliegende Situation richtig sehe, dann sollte Programm1 die lock-Methode einsetzen, um die Datei während eines Schreibvorgangs zu sperren - darauf habe ich allerdings leider keinen direkten Einfluss.

Hier also zwei alternative Vorschläge:
1) Programm1 zeigt durch eine Zeichenkette am Dateianfang an, ob die Datei gerade bearbeitet wird oder gelesen werden kann. Diese Zeichenkette setzt sie als ersten und letzten Schritt jeden Schreibvorganges. Wenn Programm2 beim Auslesen feststellt, dass die Datei bearbeitet wird, wird der Auslesevorgang beendet.
Falls meine Vermutung oben falsch war, kann eine Änderung während des Lesevorgangs (nach der Überprüfung der Zeichenkette) dann allerdings immernoch zu falschen Ergebnissen führen.


2) Programm2 prüft beim Auslesen immer, ob das erwartete Format eines vollständigen Wertes gegeben ist. Ist es das nicht, wird in diesem Einlesevorgang nichts getan. Das ist nicht sondernlich dramatisch, da Programm1 in einer sehr langsamen Frequenz, Programm2 hingegen in einer sehr hohen Frequenz arbeitet.
Meiner Meinung nach müsste dieses Verfahren selbst dann funktionieren, wenn meine Vermutung oben falsch war, da das Format einer bereits eingelesenen Zeichenkette überprüft wird, deren Inhalt dann ja nun wirklich nicht mehr verändert werden kann. Probleme könnte es nur geben, wenn der Inhalt so schnell verändert wird, dass ein "Treffer" im richtigen Moment die Ausnahme wird und Programm2 den Auslesevorgang ständig abbrechen muss - das ist wie gerade beschrieben aber ja nicht der Fall.

Von diesen beiden Vorschlägen favorisiere ich derzeit Lösung 2 - allerdings bin ich mir bei beiden nicht sicher, ob sie das Problem wirklich zuverlässig lösen. Von daher wäre ich um Kritik oder Vorschläge sehr dankbar!

Vielen Dank für's Lesen und einen schönen Abend!
muhazz


----------



## irgendjemand (1. Mrz 2012)

hatten wir doch neulich erst ...

leute ... nutzt doch mal SUFU und google ...

ohne deinen post gelesen zu haben : DAS GEHT NICHT

du kannst zwar eine datei die ein anderes programm schreibt lesen *sofern kein exklusiver zugriff erzeugt wurde* ... aber um veränderungen mitzubekommen musst du die datei immer wieder neu lesen ...

lösung : pipes , sockets , stream , datenbank , etc ...

wobei ich denke das ne datenbank das einfachste wäre ...


----------



## KrokoDiehl (2. Mrz 2012)

Es gibt sicher andere Methoden in Java um Dateien zu Lesen, die anderswo beschrieben werden (z.B. RandomAccessFile (Java Platform SE 7 )). Wobei nie sicher ist, dass das was Programm1 gerade schreibt auch von Programm2 gerade gelesen wird - dafür sind Dateien nicht da, weil einige andere "Dinge" dazwischen hängen. Nur weil ein Programm1 ein "write( blablabla )" ausführt landet das nicht sofort in der Datei auf der Festplatte.

Aber per se kann man Dateien schon Lesen, während sie anderswo geschrieben werden. Nur was dort an verwertbaren Daten herauskommt ist eine völlig andere Sache. Mit Java 7 gibt es auch die Möglichkeit über Dateiänderungen benachrichtigt zu werden (--> googlen).

Über die NIO-API gibt es auch Möglichkeiten Dateien zu sperren, aber auch hier ist äußerst fraglich, ob das ein guter Synchronisations-Rhythmus ist. Zumal ich dein Programm1 ja so verstanden habe, dass es außerhalb deiner Kontrolle liegt und "zufällig" arbeitet. Wie will man mit sowas interagieren?

Wenn beide Programme (gleichzeitig) die Datei beschreiben wollen wird das über Dateien ohnehin maximal komplex


----------



## muhazz (2. Mrz 2012)

irgendjemand hat gesagt.:


> ohne deinen post gelesen zu haben : DAS GEHT NICHT



Um von deinen nachfolgenden Bemerkungen zu schließen: Das hättest du besser mal getan.



@KrokoDiehl: Danke für deine Antwort. Wie gesagt, ich glaube auch nicht, dass NIO-Klassen hier weiterhelfen könnten. Leider glaube ich auch nicht, dass die RandomAccessFile-Klasse das Problem löst. Es scheint einfach eine sehr ungünstige Situation zu sein.

Aber um nochmal auf mein eigentliches *Hauptanliegen *zu verweisen:


			
				muhazz hat gesagt.:
			
		

> Programm2 prüft beim Auslesen immer, ob das erwartete Format eines vollständigen Wertes gegeben ist. Ist es das nicht, wird in diesem Einlesevorgang nichts getan.


Vorausgesetzt, dass Programm1 in einer sehr hohen Taktrate ausliest und Programm2 eher selten einen Wert in der Datei ändert, dann könnte damit doch schon das Problem gelöst sein. Was meint ihr dazu?


----------



## irgendjemand (2. Mrz 2012)

@TO

das einzige was ich gelesen habe war folgender satz : "Ein mir nicht näher bekanntes Programm ("Programm1") aktualisiert ständig den Inhalt einer Textdatei, den ich mit einem weiteren Programm ("Programm2") auslesen soll." ... mehr nicht ... *weils mich auch nicht weiter intressiert hat*

meine antwort bezog sich lediglich auf den terminus das datein für diese art von informations-austausch zwischen zwei programmen mit abstand die schlechtest wahl auf modernen systemen sind ... *noch heftiger wäre wohl sowas wie n band-laufwerk* ...

eine deutlich einfachere variante wären z.b. pipes zur dierekten interprozess-kommunikation ... oder falls das nicht möglich ist eine datenbank ... an die man dann sinnvolle queries absetzt ... und dank der verwendung von timestamps auch immer nur die daten eines bestimmten zeitraums bekommen würde ...

das problem liegt hier wohl viel eher daran das du die quelle der daten *dein "Programm1"* nicht soweit abändern kannst um dir diese einfachen möglichkeiten zu nutze zu machen ...

aber ständig ein log-file lesen ist definitiv schlechtes design ... mit sicherheit auch nicht gerade performant ... und belastet die gesamte hardware mehr als andere verfahren mit caching und der gleichen ...


----------



## Dyed (4. Mrz 2012)

Also ganz neuer Vorschlag von meiner Seite.

Wenn ich das richtig verstanden habe, möchtest du "gleichzeitig" eine Datei lesen und bearbeiten können.
Also ich hätte das so gemacht, dass du von Anfang an sagst, dass du eine Textdatei hast, wo du was reinschreiben tust und eine Textdatei hast, wo du das auslesen tust.
Das heißt, du brauchst 2 Textdateien und musst dein Code ein bisschen umprogrammieren.
Also, wenn du jetzt 2 Textdateien hast, würde ich mir einen Timer (oder irgendwelche Kriterien) programmieren, der in einen bestimmten Rhythmus den Text aus der ersten in die zweite Textdatei kopiert.
Damit vermeidest du die Kollision zwischen BufferedReader und BufferedWriter.


----------



## KrokoDiehl (5. Mrz 2012)

> Programm2 prüft beim Auslesen immer, ob das erwartete Format eines vollständigen Wertes gegeben ist. Ist es das nicht, wird in diesem Einlesevorgang nichts getan.



Sowas kannst du natürlich machen und so eine Datenprüfung sorgt auch dafür, dass deine Daten in Programm2 gültig bleiben. An dem Ansatz ist soweit nichts auszusetzen.

Der Performanz-Gesichtspunkt sollte natürlich bedacht werden, denn jenachdem wie groß die Datei bzw. wie aufwendig die Prüfung ist - natürlich auch wie häufig du prüfst - kann das zum Flaschenhals werden. Aber andererseits heißt es auch, man solle sich Performanzproblemen dann annehmen, wenn man welche hat 

Echtzeit-Updates bekommst du damit aber keinesfalls hin.


----------

