Ich verwende zum Locken java.nio.channels.FileLock
.
Siehe auch
http://vafer.org/blog/20060806175846/
Mein zum Testen und hier Posten aus verschiedenen Klassen zusammenkopierter Code
package fileLock;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.channels.FileChannel;
import java.nio.channels.OverlappingFileLockException;
/*
* Fürs Locking siehe auch:
* http://vafer.org/blog/20060806175846/
* https://examples.javacodegeeks.com/core-java/nio/channels/filelock-channels/java-nio-channels-filelock-example/
*/
public class CanNotReadLockedFile {
private java.nio.channels.FileLock lock;
private RandomAccessFile file;
private String filename;
private String rights;
public CanNotReadLockedFile() {
filename = "c:/temp/testdatei_zum_locken.txt";
rights = "rw";
}
public void run() {
if (lock()) {
say("lock gained");
runLocked();
unlock();
}
}
private void runLocked() {
try {
tryToRunLocked();
}
catch (Exception exception) {
exception.printStackTrace();
}
}
private void tryToRunLocked() throws IOException {
LineNumberReader reader = openReader();
String line;
while (null != (line = reader.readLine())) {
say("Eingelesene Zeile: '" + line + "' in Zeile " + reader.getLineNumber());
}
reader.close();
}
/* --- DATEI LESEN --- */
private LineNumberReader openReader() {
try {
return tryToOpenReader();
}
catch (FileNotFoundException e) {
throw new RuntimeException("Die Eingabedatei '" + filename
+ "' wurde nicht gefunden. (" + e.getMessage() + ")");
}
catch (UnsupportedEncodingException e) {
throw new RuntimeException(
"Bei der Erzeugung des " + "InputStreamReaders für die Eingabedatei '"
+ filename + "' wurde eine nicht unterstützte Kodierung verwendet. ("
+ e.getMessage() + ")");
}
}
private LineNumberReader tryToOpenReader()
throws FileNotFoundException, UnsupportedEncodingException {
InputStream inputStream = new FileInputStream(filename);
InputStreamReader reader = new InputStreamReader(inputStream, "ISO-8859-1");
return new LineNumberReader(reader);
}
/* --- LOCKING --- */
boolean lock() {
if (null != lock) {
return false;
}
say("Versuche Lock auf " + filename + " zu erhalten ...");
boolean success = lockInternal();
if (success) {
say("Lock auf " + filename + " erhalten.");
say("Lock is shared: " + lock.isShared());
}
else {
say("Kein Lock erhalten, lock = " + lock);
lock = null;
}
return success;
}
private boolean lockInternal() {
file = openRandomAccessFile();
FileChannel channel = file.getChannel();
say("Versuch den exclusiven Lock zu erhalten...");
tryToLock(channel);
if (null == lock) {
say("Lock kann nicht erhalten werden. lock == null.");
closeFile();
return false;
}
return true;
}
private RandomAccessFile openRandomAccessFile() {
try {
return new RandomAccessFile(filename, rights);
}
catch (FileNotFoundException exception) {
throw new RuntimeException(exception);
}
}
private void closeFile() {
try {
file.close();
}
catch (IOException exception) {
throw new RuntimeException(exception);
}
file = null;
}
private boolean tryToLock(FileChannel channel) {
try {
lock = channel.tryLock(); // gets an exclusive lock
}
catch (IOException exception) {
say("Lock kann nicht erhalten werden. IOException.");
return false;
}
catch (OverlappingFileLockException exception) {
say("Lock kann nicht erhalten werden. OverlappingFileLockException.");
return false;
}
return true;
}
private boolean unlock() {
if (null == lock) {
return false;
}
say("Versuche Lock auf " + filename + " zu lösen ...");
boolean success = tryToUnlock();
if (success) {
say("Lock auf " + filename + " gelöst.");
}
lock = null;
closeFile();
return success;
}
private boolean tryToUnlock() {
try {
lock.release();
}
catch (IOException exception) {
say("Lösen war nicht erfolgreich: " + exception.getMessage());
exception.printStackTrace();
return false;
}
return true;
}
private void say(String message) {
System.out.println(message);
}
public static void main(String[] args) {
new CanNotReadLockedFile().run();
}
}
läuft auf den Fehler Der Prozess kann nicht auf die Datei zugreifen, da ein anderer Prozess einen Teil der Datei gesperrt hat
, vermutlich weil ich einen eigenen Reader auf der Datei geöffnet habe und nicht über das RandomAccessFile
auf die Datei zugreife.
Er erzeugt folgende Ausgabe:
Versuche Lock auf c:/temp/testdatei_zum_locken.txt zu erhalten ...
Versuch den exclusiven Lock zu erhalten...
Lock auf c:/temp/testdatei_zum_locken.txt erhalten.
Lock is shared: false
lock gained
java.io.IOException: Der Prozess kann nicht auf die Datei zugreifen, da ein anderer Prozess einen Teil der Datei gesperrt hat
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:255)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.LineNumberReader.readLine(LineNumberReader.java:201)
at fileLock.CanNotReadLockedFile.tryToRunLocked(CanNotReadLockedFile.java:54)
at fileLock.CanNotReadLockedFile.runLocked(CanNotReadLockedFile.java:43)
at fileLock.CanNotReadLockedFile.run(CanNotReadLockedFile.java:36)
at fileLock.CanNotReadLockedFile.main(CanNotReadLockedFile.java:198)
Versuche Lock auf c:/temp/testdatei_zum_locken.txt zu lösen ...
Lock auf c:/temp/testdatei_zum_locken.txt gelöst.
Muss ich mich jetzt mit dem RandomAccessFile
auseinandersetzen, oder gibt es einen anderen, eleganten Weg? Momentan hab ich es so gelöst, dass ich nicht diese Datei selbst locke, sondern eine andere extra nur zum Locken angelegte Datei. Ich weiß aber nicht, ob das so richtig elegant ist.