java - txt - file.delete() devuelve falso aunque file.exists(), file.canRead(), file.canWrite(), file.canExecute() todos devuelven true
java fileoutputstream txt (16)
Estoy intentando eliminar un archivo, después de escribir algo en él, con FileOutputStream
. Este es el código que uso para escribir:
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 se ve, limpio y cierro el flujo, pero cuando intento eliminarlo, file.delete()
devuelve falso.
Revisé antes de la eliminación para ver si el archivo existe, y: file.exists()
, file.canRead()
, file.canWrite()
, file.canExecute()
todos devuelven true. Justo después de llamar a estos métodos pruebo file.delete()
y file.delete()
falso.
¿Hay algo que haya hecho mal?
PARA Eclipse / NetBeans
Reinicie su IDE y vuelva a ejecutar su código. Esto es solo un truco para mí después de una hora de lucha.
Aquí está mi código:
File file = new File("file-path");
if(file.exists()){
if(file.delete()){
System.out.println("Delete");
}
else{
System.out.println("not delete");
}
}
Salida:
Borrar
Antes de intentar eliminar / cambiar el nombre de cualquier archivo, debe asegurarse de que todos los lectores o escritores (por ejemplo, BufferedReader
/ InputStreamReader
/ BufferedWriter
) estén correctamente cerrados.
Cuando intenta leer / escribir sus datos desde / hacia un archivo, el proceso mantiene el archivo y no se libera hasta que se completa la ejecución del programa. Si desea realizar las operaciones de eliminar / cambiar el nombre antes de que finalice el programa, debe usar el método close()
que viene con las clases java.io.*
.
Como comentó Jon Skeet, debe cerrar su archivo en el bloque finally {...} para asegurarse de que esté siempre cerrado. Y, en lugar de tragar las excepciones con e.printStackTrace, simplemente no atrape y agregue la excepción a la firma del método. Si no puede por alguna razón, al menos haga esto:
catch(IOException ex) {
throw new RuntimeException("Error processing file XYZ", ex);
}
Ahora, pregunta número 2:
¿Qué pasa si haces esto?
...
to.close();
System.out.println("Please delete the file and press <enter> afterwards!");
System.in.read();
...
¿Podrías borrar el archivo?
Además, los archivos se vacían cuando están cerrados. Yo uso IOUtils.closeQuietly (...), así que utilizo el método flush para asegurarme de que el contenido del archivo esté allí antes de intentar cerrarlo (IOUtils.closeQuietly no arroja excepciones). Algo como esto:
...
try {
...
to.flush();
} catch(IOException ex) {
throw new CannotProcessFileException("whatever", ex);
} finally {
IOUtils.closeQuietly(to);
}
Entonces sé que el contenido del archivo está ahí. Como generalmente me importa que el contenido del archivo esté escrito y no si el archivo se puede cerrar o no, realmente no importa si el archivo se cerró o no. En su caso, como es importante, le recomiendo que cierre el archivo usted mismo y que trate las excepciones de acuerdo con esto.
El problema podría ser que el archivo todavía se ve como abierto y bloqueado por un programa; o tal vez es un componente de su programa que se abrió, por lo que debe asegurarse de utilizar el método dispose()
para resolver ese problema. es decir, JFrame frame; .... frame.dispose();
JFrame frame; .... frame.dispose();
Espero que esto ayude. Me encontré con un problema similar en el que no pude eliminar mi archivo después de que mi código java hizo una copia del contenido a la otra carpeta. Después de hacer búsquedas en Google exhaustivas, declare explícitamente todas las variables relacionadas con la operación de archivo y llamé al método close () de cada objeto de operación de archivo y las establecí en NULL. Luego, hay una función llamada System.gc (), que borrará el archivo de asignación de E / S (no estoy seguro, solo digo lo que se da en los sitios web).
Aquí está mi código de ejemplo:
public void start() {
File f = new File(this.archivePath + "//" + this.currentFile.getName());
this.Copy(this.currentFile, f);
if(!this.currentFile.canWrite()){
System.out.println("Write protected file " +
this.currentFile.getAbsolutePath());
return;
}
boolean ok = this.currentFile.delete();
if(ok == false){
System.out.println("Failed to remove " + this.currentFile.getAbsolutePath());
return;
}
}
private void Copy(File source, File dest) throws IOException {
FileInputStream fin;
FileOutputStream fout;
FileChannel cin = null, cout = null;
try {
fin = new FileInputStream(source);
cin = fin.getChannel();
fout = new FileOutputStream(dest);
cout = fout.getChannel();
long size = cin.size();
MappedByteBuffer buf = cin.map(FileChannel.MapMode.READ_ONLY, 0, size);
cout.write(buf);
buf.clear();
buf = null;
cin.close();
cin = null;
fin.close();
fin = null;
cout.close();
cout = null;
fout.close();
fout = null;
System.gc();
} catch (Exception e){
this.message = e.getMessage();
e.printStackTrace();
}
}
Fue bastante extraño el truco que funcionó. El caso es que cuando leí el contenido del archivo, utilicé BufferedReader
. Después de leer, cerré el buffer.
Mientras tanto, cambié y ahora estoy leyendo el contenido usando FileInputStream
. También después de terminar de leer, cierro la transmisión. Y ahora está funcionando.
El problema es que no tengo la explicación para esto.
No sé que BufferedReader
y FileOutputStream
sean incompatibles.
Hubo un problema una vez en ruby, donde los archivos en Windows necesitaban una "fsync" para realmente poder dar la vuelta y volver a leer el archivo después de escribirlo y cerrarlo. Tal vez esta es una manifestación similar (y si es así, creo que un error de Windows, realmente).
Intenté esta cosa simple y parece estar funcionando.
file.setWritable(true);
file.delete();
Esto funciona para mi.
Si esto no funciona, intente ejecutar su aplicación Java con sudo si está en Linux y como administrador cuando está en Windows. Solo para asegurarnos de que Java tenga los derechos para cambiar las propiedades del archivo.
Ninguna de las soluciones enumeradas aquí funcionó en mi situación. Mi solución fue usar un ciclo while, intentando borrar el archivo, con un límite de seguridad de 5 segundos (configurable).
File f = new File("/path/to/file");
int limit = 20; //Only try for 5 seconds, for safety
while(!f.delete() && limit > 0){
synchronized(this){
try {
this.wait(250); //Wait for 250 milliseconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
limit--;
}
El uso del bucle anterior funcionó sin tener que realizar ninguna recolección manual de basura ni configurar la transmisión como nula, etc.
No hay ninguna razón por la que no puedas eliminar este archivo. Me gustaría ver quién tiene un control sobre este archivo. En Unix / Linux, puede usar la utilidad lsof para verificar qué proceso tiene un bloqueo en el archivo. En Windows, puede usar Process Explorer.
para lsof, es tan simple como decir:
lsof /path/and/name/of/the/file
para el explorador de procesos puede usar el menú Buscar e ingresar el nombre del archivo para mostrarle el identificador que lo dirigirá al proceso de bloqueo del archivo.
aquí hay un código que hace lo que creo que debes hacer:
FileOutputStream to;
try {
String file = "/tmp/will_delete.txt";
to = new FileOutputStream(file );
to.write(new String("blah blah").getBytes());
to.flush();
to.close();
File f = new File(file);
System.out.print(f.delete());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Funciona bien en OS X. No lo he probado en Windows, pero sospecho que también debería funcionar en Windows. También admitiré haber visto algún comportamiento inesperado en el manejo de archivos de Windows wrt.
Otro error en Java. Pocas veces los encuentro, solo el segundo en mis 10 años de carrera. Esta es mi solución, como otros lo han mencionado. He usado System.gc()
. Pero aquí, en mi caso, es absolutamente crucial. ¿Extraño? ¡SÍ!
finally
{
try
{
in.close();
in = null;
out.flush();
out.close();
out = null;
System.gc();
}
catch (IOException e)
{
logger.error(e.getMessage());
e.printStackTrace();
}
}
Si está trabajando en Eclipse IDE, eso podría significar que no ha cerrado el archivo en el inicio anterior de la aplicación. Cuando tuve el mismo mensaje de error al intentar eliminar un archivo, esa fue la razón. Parece que Eclipse IDE no cierra todos los archivos después de la finalización de una aplicación.
Tienes que cerrar todas las secuencias o usar el bloque try-with-resource
static public String head(File file) throws FileNotFoundException, UnsupportedEncodingException, IOException
{
final String readLine;
try (FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
LineNumberReader lnr = new LineNumberReader(isr))
{
readLine = lnr.readLine();
}
return readLine;
}
Tuve el mismo problema en Windows. Solía leer el archivo en scala línea por línea con
Source.fromFile(path).getLines()
Ahora lo leo en su totalidad con
import org.apache.commons.io.FileUtils._
// encoding is null for platform default
val content=readFileToString(new File(path),null.asInstanceOf[String])
que cierra el archivo correctamente después de leer y ahora
new File(path).delete
trabajos.
la respuesta es cuando cargas el archivo, necesitas aplicar el método "cerrar", en cualquier línea de código, me funciona
si file.delete () está enviando falso, en la mayoría de los casos, su identificador Bufferedreader no se cerrará. Solo cerca y parece funcionar para mí normalmente.