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.

Foi útil?

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

Filechannel.lock ()

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top