Question

J'ai un processus Java qui ouvre un fichier à l'aide d'un FileReader. Comment puis-je empêcher un autre processus (Java) d'ouvrir ce fichier ou au moins informer ce deuxième processus que le fichier est déjà ouvert? Cela crée-t-il automatiquement une exception si le fichier est ouvert (ce qui résout mon problème) ou dois-je l’ouvrir explicitement dans le premier processus avec une sorte de drapeau ou un argument?

Pour préciser:

J'ai une application Java qui répertorie un dossier et ouvre chaque fichier de la liste pour le traiter. Il traite chaque fichier l'un après l'autre. Le traitement de chaque fichier consiste à le lire et à effectuer des calculs en fonction du contenu et prend environ 2 minutes. J'ai également une autre application Java qui fait la même chose mais écrit à la place sur le fichier. Ce que je veux, c'est pouvoir exécuter ces applications en même temps, donc le scénario est comme ça. ReadApp répertorie le dossier et trouve les fichiers A, B, C. Il ouvre le fichier A et lance la lecture. WriteApp répertorie le dossier et trouve les fichiers A, B, C. Il ouvre le fichier A, voit qu’il est ouvert (par une exception ou de quelque manière que ce soit) et passe au fichier B. ReadApp termine le fichier A et continue vers le fichier B. est ouvert et continue jusqu'à C. Il est essentiel que WriteApp n'écrive pas pendant que ReadApp lit le même fichier, ou inversement. Ce sont des processus différents.

Était-ce utile?

La solution

FileChannel.lock est probablement ce que vous voulez.

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

(Avertissement: code non compilé et certainement pas testé.)

Notez la section "Dépendances de la plateforme". dans le doc d'API pour FileLock .

Autres conseils

N'utilisez pas les classes du package java.io , utilisez plutôt le package java.nio . Ce dernier a une classe FileLock . Vous pouvez appliquer un verrou à 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) {
    }

Si vous pouvez utiliser Java NIO ( JDK version 1.4 ou supérieure ), je pense que vous recherchez java.nio.channels.FileChannel.lock ()

FileChannel.lock ()

Ce n'est peut-être pas ce que vous recherchez, mais dans l'intérêt de résoudre un problème sous un autre angle ....

Ces deux processus Java pourraient-ils vouloir accéder au même fichier dans la même application? Peut-être pouvez-vous simplement filtrer tous les accès au fichier via une seule méthode synchronisée (ou, mieux encore, avec JSR-166 )? De cette façon, vous pouvez contrôler l’accès au fichier et peut-être même les demandes d’accès à la file d’attente.

Utilisez un fichier RandomAccessFile, obtenez son canal, puis appelez lock (). Le canal fourni par les flux d'entrée ou de sortie ne dispose pas des privilèges suffisants pour se verrouiller correctement. Assurez-vous d'appeler unlock () dans le bloc finally (la fermeture du fichier ne libère pas nécessairement le verrou).

J'ai trouvé le même problème il y a quelques années lorsque j'ai écrit une application nécessitant que plusieurs utilisateurs sous MacOS / Windows partagent les mêmes données dans plusieurs fichiers. Le verrouillage de fichier ne fonctionnant pas sous MacOS, j'ai donc créé ma propre classe 'ioFile' qui conserve son propre registre d'accès aux fichiers - open r / o, open r / w, etc., et à qui appartient le verrou. C’est la seule façon à l’époque de pouvoir contrôler l’accès de différents utilisateurs sur différentes machines utilisant différents systèmes d’exploitation.

Vous trouverez ci-dessous un exemple de code d'extrait permettant de verrouiller un fichier jusqu'à son traitement par la 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();
        }
    }

}

Si vous mettez votre accès au fichier dans un bloc synchronisé, une seule instance de thread peut y entrer, les autres attendent jusqu'à ce que l'une d'entre elles ait terminé son travail.

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

     }  

Vous pouvez utiliser les API java.nio. * pour verrouiller un fichier. Cependant, cela ne garantit pas le verrouillage. Cela dépend si le système d'exploitation sous-jacent prend en charge le verrouillage ou non. Si je comprends bien, les systèmes d'exploitation tels que Linux ne prennent pas en charge le verrouillage. Vous ne pouvez donc pas le verrouiller, même si vous utilisez ces API

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top