web-dev-qa-db-fra.com

Comment verrouiller un fichier avec Java (si possible)

J'ai un processus Java qui ouvre un fichier en utilisant 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?

Clarifier:

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 cela. 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 s’il est ouvert (par une exception ou de quelque manière que ce soit) et passe au 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.

102
Paralife

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 intitulée "dépendances de plate-forme" dans la doc API pour FileLock .

101

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 à une 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) {
    }
48
ayengin

Si vous pouvez utiliser Java NIO (JDK 1.4 ou supérieur), alors je pense que vous cherchez Java.nio.channels.FileChannel.lock()

FileChannel.lock ()

16
KC Baltz
6
Matt

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 ....

S'agit-il de deux processus Java susceptibles d'accéder au même fichier dans la même application? Peut-être pouvez-vous simplement filtrer tous les accès au fichier à l'aide d'une seule méthode synchronisée (ou, mieux encore, en utilisant JSR-166 )? De cette façon, vous pouvez contrôler l'accès au fichier et peut-être même faire la queue aux demandes d'accès.

5
pkaeding

Utilisez un 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. Veillez à appeler unlock () dans le bloc finally (la fermeture du fichier ne libère pas nécessairement le verrou).

3
Kevin Day

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 a maintenu son propre registre d’accès aux fichiers - open r/o, open r/w, etc., et qui est 'propriétaire' du verrou . C’est le seul moyen à ce moment-là de contrôler l’accès de différents utilisateurs sur différentes machines. en utilisant différents systèmes d'exploitation.

0
user3654656

Vous trouverez ci-dessous un exemple de code d'extrait permettant de verrouiller un fichier jusqu'à son traitement par la machine virtuelle Java 

 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