Bloqueio de arquivos Java e Windows - o bloqueio não é “absoluto”?
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
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?)