open - paths java
Cómo puedo bloquear un archivo usando Java(si es posible) (11)
Tengo un proceso de 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 automáticamente hace 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 después del otro. El procesamiento de cada archivo consiste en leerlo y hacer algunos cálculos en función de los contenidos y lleva unos 2 minutos. También tengo otra aplicación Java que hace lo mismo pero escribe en el archivo. Lo que quiero es poder ejecutar estas aplicaciones al mismo tiempo para que el escenario sea así. ReadApp lista la carpeta y encuentra los archivos A, B, C. Abre el archivo A y comienza 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 de cualquier forma) y va al archivo B. ReadApp finaliza el archivo A y continúa en B. Lo ve está abierto y continúa hacia C. Es crucial que WriteApp no escriba mientras ReadApp lee el mismo archivo o viceversa. Son procesos diferentes.
A continuación, se muestra un código de fragmento de muestra para bloquear un archivo hasta que JVM realice su 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();
}
}
}
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 funcionaba 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 ''poseía'' el bloqueo. Esta es la única forma en que podía controlar el acceso de diferentes usuarios en diferentes máquinas usando diferentes sistemas operativos.
Esto puede no ser lo que está buscando, pero con el interés de llegar a un problema desde otro ángulo ...
¿Estos dos procesos Java pueden querer acceder al mismo archivo en la misma aplicación? ¿Quizás pueda filtrar todo el acceso al archivo a través de un único método sincronizado (o, mejor aún, utilizando JSR-166 )? De esta forma, puede controlar el acceso al archivo y, tal vez, incluso las solicitudes de acceso en cola.
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).
Tenga en cuenta la sección titulada "dependencias de plataforma" en el documento API para FileLock .
No use las clases en el paquete java.nio
, 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 pones tu acceso a archivos en bloque sincronizado, solo una instancia de hilo puede ingresar, otros esperarán, hasta que uno haya terminado su trabajo.
public class FileReader{
public void read() {
synchronized (this) {
//put you file access here
}
}
}
Si puede usar Java NIO ( JDK 1.4 o superior ), entonces creo que está buscando java.nio.channels.FileChannel.lock()
Use un RandomAccessFile, obtenga su canal, luego llame a lock (). El canal proporcionado por las secuencias de entrada o salida no tiene suficientes privilegios para bloquearse correctamente. Asegúrese de llamar a desbloquear () en el bloque finally (cerrar el archivo no necesariamente libera el bloqueo).
Usted usa las API de 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. Como yo entiendo, los sistemas operativos como Linux no admiten bloqueo y, por lo tanto, no se puede bloquear incluso si usa estas API
utiliza java.nio.channels.FileLock junto con java.nio.channels.FileChannel
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();
}
}