Pregunta

Tengo un proceso Java que abre un archivo usando un FileReader. ¿Cómo puedo evitar que otro proceso (Java) abra este archivo, o al menos notifique a ese segundo proceso que el archivo ya está abierto? ¿Esto hace automáticamente que el segundo proceso obtenga una excepción si el archivo está abierto (lo que resuelve mi problema) o tengo que abrirlo explícitamente en el primer proceso con algún tipo de indicador o argumento?

Para aclarar:

Tengo una aplicación Java que enumera una carpeta y abre cada archivo en la lista para procesarla. Procesa cada archivo tras otro. El procesamiento de cada archivo consiste en leerlo y hacer algunos cálculos basados ??en el contenido y demora aproximadamente 2 minutos. También tengo otra aplicación Java que hace lo mismo pero que escribe en el archivo. Lo que quiero es poder ejecutar estas aplicaciones al mismo tiempo para que el escenario sea así. ReadApp muestra la carpeta y encuentra los archivos A, B, C. Abre el archivo A e inicia la lectura. WriteApp enumera la carpeta y encuentra los archivos A, B, C. Abre el archivo A, ve que está abierto (por una excepción o lo que sea) y va al archivo B. ReadApp finaliza el archivo A y continúa hasta B. Ve que está abierto y continúa a C. Es crucial que WriteApp no ??escriba mientras ReadApp está leyendo el mismo archivo o viceversa. Son procesos diferentes.

¿Fue útil?

Solución

FileChannel.lock es probablemente lo que quieres.

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

(Descargo de responsabilidad: Código no compilado y ciertamente no probado)

Observe la sección titulada " dependencias de plataforma " en la documento API para FileLock .

Otros consejos

No utilice las clases en el paquete java.io , en su lugar use el paquete java.nio . Este último tiene una clase FileLock . Puede aplicar un bloqueo 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) {
    }

Si puede usar NIO de Java ( JDK 1.4 o superior ), creo que está buscando java.nio.channels.FileChannel.lock ()

FileChannel.lock ()

Puede que esto no sea lo que está buscando, pero con el interés de encontrar un problema desde otro ángulo ...

¿Estos dos procesos de Java pueden querer acceder al mismo archivo en la misma aplicación? Quizás pueda simplemente filtrar todos los accesos al archivo a través de un método único y sincronizado (o, mejor aún, usando JSR-166 )? De esa manera, puede controlar el acceso al archivo, y quizás incluso las solicitudes de acceso a la cola.

Use un RandomAccessFile, obtenga su canal, luego llame a lock (). El canal proporcionado por los flujos de entrada o salida no tiene suficientes privilegios para bloquearse correctamente. Asegúrese de llamar a unlock () en el bloque finally (cerrar el archivo no necesariamente libera el bloqueo).

Encontré el mismo problema hace algunos años cuando escribí una aplicación que requería que varios usuarios en MacOS / Windows compartieran los mismos datos en varios archivos. El bloqueo de archivos no funcionó en MacOS, así que creé mi propia clase 'ioFile' que mantenía su propio registro de acceso a archivos: abrir r / o, abrir r / w, etc., y quién era el dueño del bloqueo. Esta es la única forma en el momento en que podría controlar el acceso de diferentes usuarios en diferentes máquinas utilizando diferentes sistemas operativos.

A continuación se muestra un código de fragmento de código de ejemplo para bloquear un archivo hasta que JVM realiza el proceso.

 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 pones el acceso a tu archivo en un bloque sincronizado, solo una instancia del subproceso puede entrar en él, otros esperarán hasta que uno haya terminado su trabajo.

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

     }  

Usted puede usar las API java.nio. * para bloquear un archivo. Sin embargo, eso no garantiza el bloqueo, depende de si el sistema operativo subyacente admite el bloqueo o no. Según entiendo, los sistemas operativos como Linux no admiten el bloqueo y, por lo tanto, no puede bloquearlos incluso si utiliza estas API

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top