Estou tentando excluir um arquivo, depois de escrever algo nele, com FileOutputStream
. Este é o código que uso para escrever:
private void writeContent(File file, String fileContent) {
FileOutputStream to;
try {
to = new FileOutputStream(file);
to.write(fileContent.getBytes());
to.flush();
to.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Como pode ser visto, libero e fecho o stream, mas quando tento deletar, file.delete()
retorna falso.
Eu verifiquei antes da eliminação para ver se existe o arquivo e: file.exists()
, file.canRead()
, file.canWrite()
, file.canExecute()
todo o retorno verdadeiro. Logo após chamar esses métodos, tento file.delete()
e retorna falso.
Há algo que eu fiz de errado?
java
file
fileoutputstream
Jenny Smith
fonte
fonte
Respostas:
Outro bug em Java. Eu raramente os encontro, apenas meu segundo em minha carreira de 10 anos. Esta é a minha solução, como outros mencionaram. Eu tenho nether usado
System.gc()
. Mas aqui, no meu caso, é absolutamente crucial. Esquisito? SIM!fonte
new File(path)
), encontrei o mesmo problema e adicionandoSystem.gc()
antes dedelete()
fazer funcionar!System.gc
truque funciona sempre.System.gc(); result = file.delete(); if (!result){ Thread.sleep(100); System.gc(); result = file.delete(); }
Foi muito estranho o truque que funcionou. A coisa é quando eu li anteriormente o conteúdo do arquivo, eu usei
BufferedReader
. Depois de ler, fechei o buffer.Enquanto isso troquei e agora estou lendo o conteúdo usando
FileInputStream
. Também depois de terminar de ler, fecho o riacho. E agora está funcionando.O problema é que não tenho explicação para isso.
Não sei
BufferedReader
eFileOutputStream
ser incompatível.fonte
finalize()
para garantir a limpeza? Ou talvez definidoto = null
? Consulte Forçando a finalização e a coleta de lixo .Tentei uma coisa simples e parece estar funcionando.
Funciona para mim.
Se isso não funcionar, tente executar seu aplicativo Java com sudo se estiver no Linux e como administrador no Windows. Apenas para ter certeza de que o Java tem direitos para alterar as propriedades do arquivo.
fonte
Antes de tentar excluir / renomear qualquer arquivo, você deve garantir que todos os leitores ou gravadores (por exemplo:
BufferedReader
/InputStreamReader
/BufferedWriter
) estão devidamente fechados.Quando você tenta ler / gravar seus dados de / para um arquivo, o arquivo é mantido pelo processo e não liberado até que a execução do programa seja concluída. Se você quiser realizar as operações de exclusão / renomeação antes do término do programa, deverá usar o
close()
método fornecido com asjava.io.*
classes.fonte
Como Jon Skeet comentou, você deve fechar seu arquivo no bloco finally {...}, para garantir que ele esteja sempre fechado. E, em vez de engolir as exceções com o e.printStackTrace, simplesmente não capture e adicione a exceção à assinatura do método. Se você não puder por algum motivo, pelo menos faça o seguinte:
Agora, pergunta número 2:
E se você fizer isso:
Você conseguiria excluir o arquivo?
Além disso, os arquivos são liberados quando são fechados. Eu uso IOUtils.closeQuietly (...), portanto, uso o método flush para garantir que o conteúdo do arquivo esteja lá antes de tentar fechá-lo (IOUtils.closeQuietly não lança exceções). Algo assim:
Portanto, sei que o conteúdo do arquivo está lá. Como geralmente é importante para mim que o conteúdo do arquivo seja escrito e não se o arquivo pode ser fechado ou não, realmente não importa se o arquivo foi fechado ou não. No seu caso, se for importante, eu recomendaria fechar o arquivo você mesmo e tratar todas as exceções de acordo.
fonte
Não há nenhuma razão pela qual você não possa excluir este arquivo. Gostaria de ver quem tem controle sobre este arquivo. No unix / linux, você pode usar o utilitário lsof para verificar qual processo está bloqueado no arquivo. No Windows, você pode usar o explorador de processos.
para lsof, é tão simples quanto dizer:
para o explorador de processos, você pode usar o menu localizar e inserir o nome do arquivo para mostrar o identificador que irá apontar para o processo de bloqueio do arquivo.
aqui está um código que faz o que acho que você precisa fazer:
Funciona bem no OS X. Não testei no Windows, mas suspeito que deve funcionar no Windows também. Eu também admitirei ter visto algum comportamento inesperado no manuseio de arquivos wrt do Windows.
fonte
Se você estiver trabalhando no Eclipse IDE, isso pode significar que você não fechou o arquivo na inicialização anterior do aplicativo. Quando recebi a mesma mensagem de erro ao tentar excluir um arquivo, esse foi o motivo. Parece que o Eclipse IDE não fecha todos os arquivos após o término de um aplicativo.
fonte
Espero que isso ajude. Eu me deparei com um problema semelhante em que não consegui excluir meu arquivo depois que meu código Java fez uma cópia do conteúdo para a outra pasta. Após uma extensa pesquisa no Google, declarei explicitamente todas as variáveis relacionadas à operação de arquivo e chamei o método close () de cada objeto de operação de arquivo e as defini como NULL. Em seguida, existe uma função chamada System.gc (), que limpará o mapeamento de i / o do arquivo (não tenho certeza, apenas digo o que é fornecido nos sites).
Aqui está meu código de exemplo:
fonte
a resposta é quando você carrega o arquivo, você precisa aplicar o método "close", em qualquer linha de código, funciona para mim
fonte
Houve um problema uma vez no Ruby, onde os arquivos do Windows precisavam de um "fsync" para realmente poder voltar e reler o arquivo depois de gravá-lo e fechá-lo. Talvez seja uma manifestação semelhante (e se for, acho que é um bug do Windows, na verdade).
fonte
Nenhuma das soluções listadas aqui funcionou na minha situação. Minha solução foi usar um loop while, tentando excluir o arquivo, com um limite de 5 segundos (configurável) para segurança.
Usar o loop acima funcionou sem ter que fazer nenhuma coleta de lixo manual ou definir o fluxo como nulo, etc.
fonte
O problema pode ser que o arquivo ainda é visto como aberto e bloqueado por um programa; ou talvez seja um componente do seu programa no qual ele foi aberto, portanto, você deve garantir o uso do
dispose()
método para resolver esse problema. ieJFrame frame; .... frame.dispose();
fonte
Você deve fechar todos os streams ou usar o bloco try-with-resource
fonte
se file.delete () está enviando false, então na maioria dos casos o identificador do Bufferedreader não será fechado. Basta fechar e parece funcionar normalmente para mim.
fonte
Eu tive o mesmo problema no Windows. Eu costumava ler o arquivo em scala linha por linha com
Agora eu leio como um todo com
que fecha o arquivo corretamente após a leitura e agora
trabalho.
fonte
Reinicie seu IDE e execute seu código novamente, este é apenas um trabalho de truque para mim depois de uma luta de uma hora.
Aqui está o meu código:
Resultado:
Excluir
fonte
Outro caso secundário em que isso pode acontecer: se você ler / gravar um arquivo JAR por meio de um
URL
e depois tentar excluir o mesmo arquivo dentro da mesma sessão JVM.A razão é que a lógica de manipulação de arquivo JAR interno do Java tende a armazenar
JarFile
entradas em cache :E cada um
JarFile
(em vez disso, aZipFile
estrutura subjacente ) teria um identificador para o arquivo, desde o momento da construção atéclose()
ser invocado:Há uma boa explicação sobre esse problema do NetBeans .
Aparentemente, existem duas maneiras de "consertar" isso:
Você pode desativar o armazenamento em cache do arquivo JAR - para o atual
URLConnection
ou para todos osURLConnection
s futuros (globalmente) na sessão JVM atual:[HACK WARNING!] Você pode limpar manualmente o
JarFile
do cache quando terminar de usá-lo. O gerenciador de cachesun.net.www.protocol.jar.JarFileFactory
é um pacote privado, mas alguma mágica de reflexão pode fazer o trabalho para você:Observação: tudo isso é baseado no codebase Java 8 (
1.8.0_144
); eles podem não funcionar com outras versões / posteriores.fonte