File.delete() возвращает false, даже если file.exists(), file.canRead(), file.canWrite(), file.canExecute() все возвращают true
Я пытаюсь удалить файл после записи чего-нибудь в нем с помощью FileOutputStream
. Это код, который я использую для записи:
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();
}
}
Как видно, я скрываю и закрываю поток, но когда я пытаюсь удалить, file.delete()
возвращает false.
Я проверил перед удалением, чтобы увидеть, существует ли файл, и: file.exists()
, file.canRead()
, file.canWrite()
, file.canExecute()
все возвращают true. Просто после вызова этих методов я попробую file.delete()
и вернет false.
Есть ли что-то, что я сделал неправильно?
Ответы
Ответ 1
Это был довольно странный трюк, который сработал. Дело в том, что когда я ранее читал содержимое файла, я использовал BufferedReader
. После чтения я закрыл буфер.
Между тем я переключился, и теперь я читаю контент, используя FileInputStream
. Также после окончания чтения я закрываю поток. И теперь он работает.
Проблема в том, что у меня нет объяснений.
Я не знаю, что BufferedReader
и FileOutputStream
несовместимы.
Ответ 2
Еще одна ошибка в Java. Я редко нахожу их, только мой второй в моей 10-летней карьере. Это мое решение, о чем говорили другие. Я использовал net System.gc()
. Но здесь, в моем случае, это абсолютно важно. Weird? ДА!
finally
{
try
{
in.close();
in = null;
out.flush();
out.close();
out = null;
System.gc();
}
catch (IOException e)
{
logger.error(e.getMessage());
e.printStackTrace();
}
}
Ответ 3
Я пробовал эту простую вещь, и, похоже, она работает.
file.setWritable(true);
file.delete();
Это работает для меня.
Если это не работает, попробуйте запустить приложение Java с помощью sudo, если на linux и как администратор, когда на окнах. Просто чтобы убедиться, что у Java есть права на изменение свойств файла.
Ответ 4
Прежде чем пытаться удалить/переименовать любой файл, вы должны убедиться, что все читатели или писатели (например: BufferedReader
/InputStreamReader
/BufferedWriter
) правильно закрыты.
Когда вы пытаетесь читать/записывать свои данные из/в файл, файл сохраняется процессом и не выводится до завершения выполнения программы. Если вы хотите выполнить операции удаления/переименования до завершения программы, вы должны использовать метод close()
, который поставляется с классами java.io.*
.
Ответ 5
Как прокомментировал Джон Скит, вы должны закрыть свой файл в блоке finally {...}, чтобы он всегда закрывался. И вместо того, чтобы проглатывать исключения с помощью e.printStackTrace, просто не поймайте и не добавьте исключение в подпись метода. Если вы не можете по какой-либо причине, по крайней мере, выполните следующее:
catch(IOException ex) {
throw new RuntimeException("Error processing file XYZ", ex);
}
Теперь номер вопроса № 2:
Что делать, если вы это сделаете:
...
to.close();
System.out.println("Please delete the file and press <enter> afterwards!");
System.in.read();
...
Можете ли вы удалить файл?
Кроме того, файлы закрываются, когда они закрыты. Я использую IOUtils.closeQuietly(...), поэтому я использую метод flush для обеспечения того, чтобы содержимое файла находилось там до того, как я попытаюсь закрыть его (IOUtils.closeQuietly не генерирует исключения). Что-то вроде этого:
...
try {
...
to.flush();
} catch(IOException ex) {
throw new CannotProcessFileException("whatever", ex);
} finally {
IOUtils.closeQuietly(to);
}
Итак, я знаю, что содержимое файла находится там. Как обычно для меня важно, что содержимое файла записано, а не если файл может быть закрыт или нет, то действительно не имеет значения, был ли файл закрыт или нет. В вашем случае, поскольку это имеет значение, я бы рекомендовал закрыть файл самостоятельно и обработать любые исключения согласно.
Ответ 6
Нет причин, по которым вы не сможете удалить этот файл. Я бы посмотрел, кто удержал этот файл. В unix/linux вы можете использовать утилиту lsof для проверки того, какой процесс имеет блокировку в файле. В Windows вы можете использовать проводник процессов.
для lsof, это так же просто, как сказать:
lsof /path/and/name/of/the/file
для проводника процессов вы можете использовать меню поиска и ввести имя файла, чтобы показать вам дескриптор, который укажет вам на процесс блокировки файла.
вот какой код, который делает то, что я думаю вам нужно сделать:
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();
}
Он отлично работает на OS X. Я не тестировал его на окнах, но я подозреваю, что он тоже должен работать на Windows. Я также допущу, что вижу какое-то неожиданное поведение в Windows w.r.t. обработки файлов.
Ответ 7
Если вы работаете в Eclipse IDE, это может означать, что вы не закрыли файл при предыдущем запуске приложения. Когда у меня было такое же сообщение об ошибке при попытке удалить файл, это и стало причиной. Кажется, Eclipse IDE не закрывает все файлы после завершения приложения.
Ответ 8
Надеюсь, это поможет. Я столкнулся с аналогичной проблемой, когда я не смог удалить свой файл после того, как мой код Java сделал копию содержимого в другую папку. После обширного поиска в Google я явно объявлял все связанные с файлом операционные переменные и называл метод close() для каждого объекта операции с файлами и устанавливал их в NULL. Тогда есть функция System.gc(), которая очистит сопоставление ввода/вывода файла (я не уверен, я просто расскажу, что дано на веб-сайтах).
Вот мой пример кода:
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();
}
}
Ответ 9
ответ - когда вы загружаете файл, вам нужно применить метод "закрыть", в любой строке кода, работает со мной
Ответ 10
Однажды в Ruby возникла проблема, когда файлы в окнах нуждались в "fsync", чтобы фактически обернуться и перечитать файл после его написания и закрытия. Возможно, это похожее проявление (и если да, я думаю, что ошибка в Windows действительно).
Ответ 11
Ни одно из перечисленных здесь решений не работало в моей ситуации. Мое решение состояло в том, чтобы использовать цикл while, пытаясь удалить файл, с 5-секундным (настраиваемым) пределом безопасности.
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--;
}
Использование вышеуказанного цикла работало без необходимости вручную собирать мусор или устанавливать поток на нуль и т.д.
Ответ 12
Проблема может заключаться в том, что файл все еще рассматривается как открытый и заблокированный программой; или, возможно, это компонент из вашей программы, в котором он был открыт, поэтому вы должны убедиться, что используете метод dispose()
для решения этой проблемы.
т.е. JFrame frame;
....
frame.dispose();
Ответ 13
Вы должны закрыть все потоки или использовать блок 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;
}
Ответ 14
Если file.delete() отправляет false, то в большинстве случаев ваш дескриптор Bufferedreader не будет закрыт. Просто близко, и это, кажется, работает для меня нормально.
Ответ 15
У меня была такая же проблема в Windows. Я читал файл в scala по строкам с помощью
Source.fromFile(path).getLines()
Теперь я прочитал его в целом с помощью
import org.apache.commons.io.FileUtils._
// encoding is null for platform default
val content=readFileToString(new File(path),null.asInstanceOf[String])
который правильно закрывает файл после прочтения и теперь
new File(path).delete
работы.
Ответ 16
ДЛЯ Eclipse/NetBeans
Перезагрузите свою среду IDE и запустите свой код снова, это всего лишь трюк для меня после одного часа борьбы.
Вот мой код:
File file = new File("file-path");
if(file.exists()){
if(file.delete()){
System.out.println("Delete");
}
else{
System.out.println("not delete");
}
}
Вывод:
Удалить