2010-02-15 10 views
19

Ich habe einen Prozess, der eher häufig von Cron aufgerufen wird, um eine Datei zu lesen, die bestimmte move-bezogene Befehle enthält. Mein Prozess muss diese Datendatei lesen und schreiben - und sie muss gesperrt bleiben, um zu verhindern, dass andere Prozesse sie während dieser Zeit berühren. Ein vollständig separater Prozess kann von einem Benutzer ausgeführt werden, um (potentiell) in dieselbe Datendatei zu schreiben/anzuhängen. Ich möchte, dass diese beiden Prozesse gut ablaufen und nur einzeln auf die Datei zugreifen.Java FileLock zum Lesen und Schreiben

Das nio FileLock schien zu sein, was ich brauchte (kurz, meine eigenen Semaphor-Typ-Dateien zu schreiben), aber ich habe Probleme, es für das Lesen zu sperren. Ich kann gut sperren und schreiben, aber wenn ich versuche, beim Lesen eine Sperre zu erzeugen, bekomme ich eine NonWritableChannelException. Ist es sogar möglich, eine Datei zum Lesen zu sperren? Scheint wie eine RandomAccessFile ist näher zu dem, was ich brauche, aber ich sehe nicht, wie man das implementiert. Hier

ist der Code, der fehlschlägt:

FileInputStream fin = new FileInputStream(f); 
FileLock fl = fin.getChannel().tryLock(); 
if(fl != null) 
{ 
    System.out.println("Locked File"); 
    BufferedReader in = new BufferedReader(new InputStreamReader(fin)); 
    System.out.println(in.readLine()); 
      ... 

Die Ausnahme wird auf der FileLock Linie geworfen.

java.nio.channels.NonWritableChannelException 
at sun.nio.ch.FileChannelImpl.tryLock(Unknown Source) 
at java.nio.channels.FileChannel.tryLock(Unknown Source) 
at Mover.run(Mover.java:74) 
at java.lang.Thread.run(Unknown Source) 

an den JavaDocs Sehen, sagt es

Ungeprüfter Ausnahme ausgelöst, wenn versucht wird, auf einen Kanal zu schreiben, die ursprünglich nicht zum Schreiben geöffnet wurde.

Aber ich muss nicht unbedingt darauf schreiben. Wenn ich versuche, einen FileOutpuStream usw. zum Schreiben zu erstellen, bin ich glücklich, bis ich versuche, einen FileInputStream für dieselbe Datei zu öffnen.

+0

Haben Sie versucht, den Aufruf der Methode mit drei Parametern, FileLock lock (Long-Position, Long-Size, Boolean Shared) zu verwenden? Ich habe noch nie die FileLock verwendet, also werde ich nicht als Antwort posten, aber ich denke, die Verwendung dieser Methode kann helfen, da es so klingt, als ob Sie eine gemeinsame Sperre und keine exklusive Sperre benötigen, da Sie in die Datei schreiben wollen hat ein Schloss drauf. – ChadNC

+0

Ich denke, die Absicht davon ist, nur Teile einer Datei zu sperren, jedoch möchte ich die gesamte Datei sperren, um mögliche Beschädigung zu verhindern. – bobtheowl2

Antwort

16

(a) Ist Ihnen bewusst, dass das Sperren der Datei andere Prozesse nicht davon abhält, sie zu berühren, außer sie verwenden auch Sperren?
(b) Sie müssen über einen beschreibbaren Kanal sperren. Holen Sie sich die Sperre über eine RandomAccessFile im "rw" -Modus und öffnen Sie dann Ihre FileInputStream. Achte darauf, beide zu schließen!

+1

a) Ja, ich werde beide Prozesse schreiben und planen, ähnliche Sperrverfahren in beiden zu implementieren b) Ich wusste nicht, dass Sie die Sperre auf die RandomAccessFile direkt erhalten können. Um den File [Input | Output] Stream zu verwenden, musste ich einen neuen FileInputStream (raf.getFD()) erstellen. Wie auch immer, den Input-Stream des RandomAccessFile-Objekts direkt verwendend, kann ich immer noch aus der Datei lesen. Danke – bobtheowl2

+0

Eh? (a) Sie können keine Sperre direkt von RandomAccessFile erhalten, Sie müssen zuerst seinen FileChannel holen; (b) RandomAccessFile verfügt nicht über Eingabestreams, aber es implementiert DataInput, sodass Sie direkt davon lesen können. – EJP

10

Es wäre besser, wenn Sie die Sperre mit tryLock(0L, Long.MAX_VALUE, true) erstellt haben.

Dies erstellt eine gemeinsame Sperre, die das richtige zum Lesen ist.

tryLock() ist eine Abkürzung für tryLock(0L, Long.MAX_VALUE, false), d. H. Sie fordert eine exklusive Schreibsperre an.

+0

Große Antwort. Dieses Programm ist bereits live, aber das könnte sicherlich in der nächsten Phase aktualisiert werden.Wir sehen jetzt so viel davon, dass exklusive Sperren in bestimmten Szenarien umständlich werden. Das werde ich beim nächsten Update unbedingt beachten. – bobtheowl2

+0

Warum sagen Sie, dass eine gemeinsame Sperre das Richtige für das Lesen ist, das hängt sicher von Ihrem Anwendungsfall ab? Wenn ich sicherstellen möchte, dass nur eine von mehreren Prozessen eine Datei liest (z. B. Agenten, die ein Upload-Verzeichnis überwachen, um neue Dateien zu verarbeiten), dann glaube ich nicht, dass eine gemeinsame Sperre erforderlich ist. – codebox

+1

Ich habe es so geschrieben, weil Lesen sich nicht gegenseitig ausschließt. Es ist tatsächlich möglich, dass mehrere Threads aus einer Datei lesen können, ohne dass es zu Interferenzen kommt, während das Schreiben immer exklusiv ist. Beachten Sie, dass dies eine Antwort auf die ursprüngliche Frage war und nicht für jede Situation als absolute Wahrheit gedacht ist. In 99% der Fälle stimmt das allerdings. – Huxi

Verwandte Themen