Pergunta

Estou tentando bloquear um arquivo com Java em ambiente Windows com Bloqueio de arquivo e eu tenho um problema:depois de bloquear o arquivo, ele ainda poderá ser acessado por outros processos, pelo menos em algum nível.

Segue código de exemplo:

public class SimpleLockExample {
    public static void main(String[] args) throws Exception {
        String filename = "loremlipsum.txt";

        File file = new File(filename);
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        FileChannel channel = raf.getChannel();

        FileLock lock = null;
        try {
            lock = channel.tryLock();
            String firstLine = raf.readLine();
            System.out.println("First line of file : " + firstLine);
            waitForEnter();
            lock.release();
        } catch (OverlappingFileLockException e) {
            e.printStackTrace();
        }

        lock.release();
        System.out.println("Lock released");

        channel.close();
    }

    private static void waitForEnter() throws Exception {
        BufferedReader reader =
                new BufferedReader(new InputStreamReader(System.in));
        reader.readLine();
        reader.close();
    }
}

Agora, quando eu bloqueio meu arquivo com este exemplo, ele está bloqueado:

  • Não pode ser excluído pelo Windows
  • Eclipse se recusa a abri-lo

...mas ainda não é totalmente à prova de balas:

  • Se eu abri-lo com o Scite (um editor de texto), por exemplo, nenhum conteúdo é mostrado, mas se eu optar por salvar o arquivo (vazio como aberto ou com algum conteúdo escrito), ele será bem-sucedido e o conteúdo do arquivo será limpo. .(nenhum conteúdo existe depois, mesmo que eu tenha escrito algo com Scite)

Existe alguma maneira de evitar que o arquivo seja totalmente substituído/limpo por outros processos com Java no Windows?

Se entendi bem, estou usando cadeado exclusivo do caixa eletrônico.Com o bloqueio compartilhado, há ainda mais coisas que podem ser feitas.

Este teste foi executado com Windows 2000.

Br, Touko

Foi útil?

Solução

Complicado, a API FileLock em si não promete muito:

Esta API de bloqueio de arquivos destina-se a mapear diretamente para a instalação de travamento nativo do sistema operacional subjacente.Assim, os bloqueios mantidos em um arquivo devem ser visíveis a todos os programas que tenham acesso ao arquivo, independentemente do idioma em que esses programas estão escritos.

Se um bloqueio realmente impede que outro programa acesse o conteúdo da região bloqueada depende do sistema e, portanto, não especificada.As instalações nativas de bloqueio de arquivos de alguns sistemas são meramente consultivas, o que significa que os programas devem observar cooperativamente um protocolo de travamento conhecido para garantir a integridade dos dados.Em outros sistemas, os bloqueios de arquivos nativos são obrigatórios, o que significa que, se um programa bloquear uma região de um arquivo, outros programas serão realmente impedidos de acessar essa região de uma maneira que viole o bloqueio.Em outros sistemas, se os bloqueios de arquivos nativos são consultivos ou obrigatórios são configuráveis ​​por arquivo.Para garantir um comportamento consistente e correto entre as plataformas, é altamente recomendável que os bloqueios fornecidos por esta API sejam usados ​​como se fossem bloqueios consultivos.

Curiosamente, a discussão sobre a API de bloqueio de arquivos quando ela estava em desenvolvimento afirmava que o sistema operacional Windows fornecia obrigatório bloqueio e no Unix apenas bloqueio consultivo.Portanto, nessa leitura, pode-se esperar que seu código funcione perfeitamente no Windows.

Eu me pergunto se o que está acontecendo é que seu editor não está modificando o arquivo, mas criando um arquivo temporário e, em seguida, manipulando as entradas do diretório para substituir a versão do arquivo que você bloqueou por uma nova versão.O Windows permitiria tal comportamento?

Eu me pergunto se você precisará recorrer ao JNI para obter o nível de controle necessário.

Outras dicas

Sua chamada para .TryLock () pode retornar nulo se não receber a trava. Do javadoc:

Um objeto de trava que representa o bloqueio recém-adquirido, ou nulo se a fechadura não puder ser adquirida porque outro programa contém uma trava sobreposta

Além disso, seu código atualmente abre o arquivo e depois Ele tenta adquirir uma fechadura. Em vez disso, você deve fazer um loop tentando obter o bloqueio e, depois de obtê -lo, abra o arquivo, leia o arquivo, feche o arquivo e desista do bloqueio. E desistir da fechadura em um finally {} Cláusula, caso seu código jogue uma exceção com a fechadura mantida. (Já teve que reiniciar uma máquina Windows apenas porque algum arquivo estava bloqueado?)

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