it-swarm.com.de

Wie kann ich eine Datei mit Java sperren (wenn möglich)

Ich habe einen Java-Prozess, der eine Datei mit einem FileReader öffnet. Wie kann ich verhindern, dass ein anderer (Java) Prozess diese Datei öffnet, oder zumindest den zweiten Prozess darüber informieren, dass die Datei bereits geöffnet ist? Führt dies automatisch dazu, dass der zweite Prozess eine Ausnahme erhält, wenn die Datei geöffnet ist (was mein Problem löst) oder muss ich sie im ersten Prozess explizit mit einer Art Flag oder Argument öffnen?

Zu klären:

Ich habe eine Java-App, die einen Ordner auflistet und jede Datei in der Liste zur Bearbeitung öffnet. Es verarbeitet jede Datei nach der anderen. Die Verarbeitung jeder Datei besteht darin, sie zu lesen und einige Berechnungen anhand des Inhalts durchzuführen. Dies dauert etwa 2 Minuten. Ich habe auch eine andere Java-App, die dasselbe tut, stattdessen in die Datei schreibt. Ich möchte diese Apps gleichzeitig ausführen können, damit das Szenario so läuft. ReadApp listet den Ordner auf und sucht die Dateien A, B, C. Er öffnet die Datei A und startet das Lesen. WriteApp listet den Ordner auf und sucht die Dateien A, B, C. Er öffnet die Datei A, sieht, ob sie geöffnet ist (durch eine Ausnahme oder auf welche Weise auch immer) und geht in die Datei B. ReadApp beendet die Datei A und fährt mit B fort ist offen und geht weiter zu C. Es ist wichtig, dass WriteApp nicht schreibt, während ReadApp dieselbe Datei liest oder umgekehrt. Sie sind verschiedene Prozesse.

102
Paralife

FileChannel.lock ist wahrscheinlich das, was Sie wollen.

FileInputStream in = new FileInputStream(file);
try {
    Java.nio.channels.FileLock lock = in.getChannel().lock();
    try {
        Reader reader = new InputStreamReader(in, charset);
        ...
    } finally {
        lock.release();
    }
} finally {
    in.close();
}

(Haftungsausschluss: Code nicht zusammengestellt und sicherlich nicht getestet.)

Beachten Sie den Abschnitt "Plattformabhängigkeiten" im API-Dokument für FileLock .

101

Verwenden Sie nicht die Klassen im Paket Java.io, sondern das Paket Java.nio. Letzteres hat eine FileLock-Klasse. Sie können eine Sperre auf eine FileChannel anwenden.

 try {
        // Get a file channel for the file
        File file = new File("filename");
        FileChannel channel = new RandomAccessFile(file, "rw").getChannel();

        // Use the file channel to create a lock on the file.
        // This method blocks until it can retrieve the lock.
        FileLock lock = channel.lock();

        /*
           use channel.lock OR channel.tryLock();
        */

        // Try acquiring the lock without blocking. This method returns
        // null or throws an exception if the file is already locked.
        try {
            lock = channel.tryLock();
        } catch (OverlappingFileLockException e) {
            // File is already locked in this thread or virtual machine
        }

        // Release the lock - if it is not null!
        if( lock != null ) {
            lock.release();
        }

        // Close the file
        channel.close();
    } catch (Exception e) {
    }
48
ayengin

Wenn Sie Java NIO (JDK 1.4 oder höher) verwenden können, denke ich, dass Sie nach Java.nio.channels.FileChannel.lock() suchen.

FileChannel.lock ()

16
KC Baltz
6
Matt

Dies ist möglicherweise nicht das, wonach Sie suchen, sondern aus einem anderen Blickwinkel.

Sind diese beiden Java-Prozesse, die möglicherweise auf dieselbe Datei in derselben Anwendung zugreifen möchten? Vielleicht können Sie einfach den gesamten Zugriff auf die Datei durch eine einzige, synchronisierte Methode filtern (oder, noch besser, mit JSR-166 )? Auf diese Weise können Sie den Zugriff auf die Datei steuern und möglicherweise sogar Zugriffsanforderungen in die Warteschlange stellen.

5
pkaeding

Verwenden Sie ein RandomAccessFile, rufen Sie den Kanal ab und rufen Sie lock () auf. Der von Eingabe- oder Ausgabestreams bereitgestellte Kanal verfügt nicht über ausreichende Berechtigungen, um ordnungsgemäß gesperrt zu werden. Rufen Sie unlock () unbedingt im finally-Block auf (das Schließen der Datei muss die Sperre nicht unbedingt aufheben).

3
Kevin Day

Ich fand das gleiche Problem vor einigen Jahren, als ich eine Anwendung schrieb, bei der mehrere Benutzer unter MacOS/Windows die gleichen Daten in mehreren Dateien gemeinsam nutzen mussten. Die Dateisperrung funktionierte nicht unter MacOS, daher erstellte ich meine eigene Klasse "ioFile" Das eigene Register des Dateizugriffs wurde beibehalten - Open R/O, Open R/W usw. und wer die Sperre "besaß". Dies ist der einzige Weg, zu dem Zeitpunkt, zu dem ich den Zugriff von verschiedenen Benutzern auf verschiedenen Computern steuern konnte verschiedene Betriebssysteme verwenden.

0
user3654656

Nachfolgend finden Sie einen Beispielcode, um eine Datei zu sperren, bis sie von JVM verarbeitet wird. 

 public static void main(String[] args) throws InterruptedException {
    File file = new File(FILE_FULL_PATH_NAME);
    RandomAccessFile in = null;
    try {
        in = new RandomAccessFile(file, "rw");
        FileLock lock = in.getChannel().lock();
        try {

            while (in.read() != -1) {
                System.out.println(in.readLine());
            }
        } finally {
            lock.release();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
0
Ajay