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");
  }
}

Вывод:

Удалить