Como posso bloquear um arquivo usando java (se possível)
Pergunta
Eu tenho um processo Java que abre um arquivo usando um fileReader. Como posso impedir que outro processo (Java) abra esse arquivo ou pelo menos notifique o segundo processo de que o arquivo já foi aberto? Isso faz com que o segundo processo tenha uma exceção se o arquivo estiver aberto (que resolve meu problema) ou eu tenho que abri -lo explicitamente no primeiro processo com algum tipo de bandeira ou argumento?
Esclarecer:
Eu tenho um aplicativo Java que lista uma pasta e abre cada arquivo na listagem para processá -lo. Ele processa cada arquivo após o outro. O processamento de cada arquivo consiste em lê -lo e fazer alguns cálculos com base no conteúdo e leva cerca de 2 minutos. Eu também tenho outro aplicativo Java que faz a mesma coisa, mas, em vez disso, grava no arquivo. O que eu quero é poder executar esses aplicativos ao mesmo tempo, para que o cenário seja assim. O Readapp lista a pasta e encontra os arquivos A, B, C. Ele abre o arquivo A e inicia a leitura. O WRiteApp lista a pasta e encontra os arquivos A, B, C. Ele abre o arquivo A, vê que está aberto (por uma exceção ou qualquer maneira) e vai para o arquivo B. ReadApp Finishes File A e continua a B. Ele vê que ele está aberto e continua para C. É crucial que o WRiteApp não escreva enquanto o ReadApp está lendo o mesmo arquivo ou vice -versa. São processos diferentes.
Solução
Filechannel.lock é provavelmente o que você deseja.
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();
}
(Isenção de responsabilidade: código não compilado e certamente não testado.)
Observe a seção intitulada "dependências da plataforma" no API DOC para FileLock.
Outras dicas
Não use as classes nojava.io
pacote, em vez disso, use o java.nio
pacote . O último tem um FileLock
classe. Você pode aplicar um bloqueio a um 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 você pode usar Java Nio (JDK 1.4 ou maior), então acho que você está procurando java.nio.channels.FileChannel.lock()
usar java.nio.channels.filelock em conjunção com java.nio.channels.FileChannel
Pode não ser o que você está procurando, mas no interesse de vir em um problema de outro ângulo ....
Esses dois processos Java que podem querer acessar o mesmo arquivo no mesmo aplicativo? Talvez você possa apenas filtrar todo o acesso ao arquivo através de um único método sincronizado (ou, ainda melhor, usando JSR-166)? Dessa forma, você pode controlar o acesso ao arquivo e talvez até solicitações de acesso à fila.
Use um RandomAccessFile, obtenha o canal e depois ligue para o bloqueio (). O canal fornecido pelos fluxos de entrada ou saída não possui privilégios suficientes para bloquear corretamente. Certifique -se de ligar para o desbloqueio () no bloco finalmente (fechar o arquivo não necessariamente libera o bloqueio).
Encontrei o mesmo problema há alguns anos quando escrevi um aplicativo que exigia que vários usuários no MacOS/Windows compartilhassem os mesmos dados em vários arquivos. O bloqueio de arquivos não funcionou no MacOS, então eu criei minha própria classe 'Iofile', que mantinha seu próprio registro de acesso a arquivos - Abra o R/O, o Open R/W, etc, e quem 'possuía' o bloqueio. Essa é a única maneira de controlar o acesso de diferentes usuários em diferentes máquinas usando os sistemas operacionais diferentes.
Abaixo está um código de snippet de amostra para bloquear um arquivo até que o processo seja feito pela 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 você colocar o acesso ao arquivo em bloco sincronizado, apenas uma instância do thread poderá entrar nele, outros esperarão, até que alguém termine seu trabalho.
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();
}
}
Você usa java.nio.* APIs para travar um arquivo. No entanto, isso não garante o bloqueio, depende se o sistema operacional subjacente suporta o bloqueio ou não. Como eu entendo, sistemas operacionais como o Linux não suportam o bloqueio e, portanto, você não pode travar, mesmo se usar essas APIs