Domanda

Ho un processo Java che apre un file usando un FileReader. Come posso impedire a un altro processo (Java) di aprire questo file o almeno notificare a quel secondo processo che il file è già aperto? Ciò rende automaticamente il secondo processo un'eccezione se il file è aperto (il che risolve il mio problema) o devo aprirlo esplicitamente nel primo processo con una sorta di flag o argomento?

Per chiarire:

Ho un'app Java che elenca una cartella e apre ogni file nell'elenco per elaborarla. Elabora ogni file dopo l'altro. L'elaborazione di ciascun file consiste nella lettura e nell'esecuzione di alcuni calcoli in base al contenuto e richiede circa 2 minuti. Ho anche un'altra app Java che fa la stessa cosa ma invece scrive sul file. Quello che voglio è essere in grado di eseguire queste app contemporaneamente, quindi lo scenario va in questo modo. ReadApp elenca la cartella e trova i file A, B, C. Apre il file A e avvia la lettura. WriteApp elenca la cartella e trova i file A, B, C. Apre il file A, vede che è aperto (con un'eccezione o in qualsiasi modo) e passa al file B. ReadApp termina il file A e continua su B. Lo vede è aperto e continua a C. È fondamentale che WriteApp non scriva mentre ReadApp sta leggendo lo stesso file o viceversa. Sono processi diversi.

È stato utile?

Soluzione

FileChannel.lock è probabilmente quello che vuoi.

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();
}

(Dichiarazione di non responsabilità: codice non compilato e certamente non testato.)

Nota la sezione intitolata "Dipendenze dalla piattaforma" nel documento API per FileLock .

Altri suggerimenti

Non usare le classi nel pacchetto java.io , invece usa il pacchetto java.nio . Quest'ultimo ha una classe FileLock . Puoi applicare un blocco a un FileChannel .

 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) {
    }

Se puoi usare Java NIO ( JDK 1.4 o successivo ), penso che stai cercando java.nio.channels.FileChannel.lock ()

FileChannel.lock ()

Questo potrebbe non essere quello che stai cercando, ma nell'interesse di affrontare un problema da un'altra prospettiva ....

Questi due processi Java potrebbero voler accedere allo stesso file nella stessa applicazione? Forse puoi semplicemente filtrare tutti gli accessi al file attraverso un singolo metodo sincronizzato (o, ancora meglio, usando JSR-166 )? In questo modo, puoi controllare l'accesso al file e forse anche le richieste di accesso in coda.

Usa un RandomAccessFile, ottieni il suo canale, quindi chiama lock (). Il canale fornito dai flussi di input o output non ha i privilegi sufficienti per bloccare correttamente. Assicurati di chiamare unlock () nel blocco finally (la chiusura del file non necessariamente rilascia il blocco).

Ho riscontrato lo stesso problema alcuni anni fa quando scrissi un'applicazione che richiedeva a più utenti su MacOS / Windows di condividere gli stessi dati in più file. Il blocco dei file non funzionava su MacOS, quindi ho creato la mia classe 'ioFile' che manteneva il proprio registro di accesso ai file - open r / o, open r / w, ecc. E chi 'possedeva' il blocco. Questo è l'unico modo al momento in cui potrei controllare l'accesso da diversi utenti su macchine diverse utilizzando sistemi operativi diversi.

Di seguito è riportato un codice di frammento di esempio per bloccare un file fino a quando il processo non viene eseguito da JVM.

 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();
        }
    }

}

Se metti l'accesso al tuo file in blocco sincronizzato, solo un'istanza di thread può entrare in esso, altri aspetteranno, fino a quando uno ha finito di funzionare.

public class FileReader{
  public void read() {
    synchronized (this) {
      //put you file access here
    }
  }
}
package tips.javabeat.nio.lock;  

import java.io.*;  
import java.nio.channels.FileChannel;  
import java.nio.channels.FileLock;  

public class FileLockTest {  

    public static void main(String[] args) throws Exception {  

       RandomAccessFile file = null;  

         FileLock fileLock = null;  

         try 

         {  

             file = new RandomAccessFile("FileToBeLocked", "rw");  

             FileChannel fileChannel = file.getChannel();  



             fileLock = fileChannel.tryLock();  

             if (fileLock != null){  

                 System.out.println("File is locked");  

                 accessTheLockedFile();  

             }  

         }finally{  

             if (fileLock != null){  

                 fileLock.release();  

             }  

         }  

     }  



     static void accessTheLockedFile(){  

        try{  

         FileInputStream input = new FileInputStream("FileToBeLocked");  

          int data = input.read();  

            System.out.println(data);  

      }catch (Exception exception){  

             exception.printStackTrace();  
        }  

     }  

Puoi usare java.nio. * API per bloccare un file. Tuttavia, ciò non garantisce il blocco, dipende dal fatto che il sistema operativo sottostante supporti il ??blocco o meno. A quanto mi risulta, i sistemi operativi come Linux non supportano il blocco e quindi non è possibile bloccare anche se si utilizzano queste API

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top