Функция удаления файла Java не работает, мой файл не удаляется и не выдает никаких ошибок

У меня есть код Java, который должен удалить мой существующий файл на моем устройстве, но он не работает, я не понимаю, почему. Он продолжает возвращать false, когда я пытаюсь использовать функцию .delete().

Вот мой код, я уже закрыл все буферы и записи, но он все еще не работает.

        File saveFile = new File("save.txt");
        File saveTemp = new File("temp.txt");
        File playerFile = new File(player.username + ".txt");
        String currentLine;
        try {
            FileWriter fw = new FileWriter(saveTemp, true);
            BufferedWriter bw = new BufferedWriter(fw);
            PrintWriter pw = new PrintWriter(bw);
            
            FileReader fr = new FileReader("save.txt");
            BufferedReader br = new BufferedReader(fr);
            
            while((currentLine = br.readLine()) != null)
            {
                if (!currentLine.equals(player.username))
                {
                    pw.println(currentLine);
                }
            }
            
            pw.flush();
            pw.close();
            fr.close();
            br.close();
            bw.close();
            fw.close();
            
            saveFile.delete();
            playerFile.delete();
            File dump = new File("save.txt");
            saveTemp.renameTo(dump);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

java.io.File API устарел. Это означает, что он устарел (вы должны прекратить его использовать), но, учитывая, что это основной API, «устарел» как термин, специально используемый в ядре, означает «когда-нибудь в ближайшее время, это вообще не будет работать», и java.io.File не является что - это будет работать через 10 лет. Но все равно не стоит его использовать. В его дизайне есть фундаментальные проблемы, которые означают, что это несовершенный API, и его нельзя (нельзя) исправить.

Один из его многочисленных недостатков заключается в том, что он не похож на Java в том, как он передает вам ошибки. Как ни странно, большая часть File API сама по себе не выдает исключений, когда что-то идет не так. Вместо этого он возвращает шаткие вещи.

Например, file.list() возвращает пустой массив, если вы запускаете его в пустом каталоге, но возвращает null, если он не может выполнить задание (например, каталог не существует, или это файл, а не каталог, или, процесс java не имеет прав на чтение). Точно так же delete() не вызывает исключения. Вместо того, чтобы указать на ошибку, он возвращает false. Это не только не похоже на Java, это также означает, что невозможно узнать, почему delete() не работает. Проблема с правами доступа? Файл не существует? Кто знает.

Простой вывод заключается в том, что вы всегда должны проверять возвращаемое значение всего, что вы делаете с объектом j.i.File, но это сокращает путь. Истинное решение состоит в том, чтобы прекратить его использовать.

У нового API тоже есть проблемы, но гораздо меньше. Это также не устарело / не рекомендуется в смысле словаря английского языка: именно так современное Java-приложение должно взаимодействовать с файлами. Вы найдете его в упаковке java.nio.file.

В отличие от j.i.File API, этот генерирует исключения, когда что-то идет не так, и эти исключения сообщают вам, что они могут быть проверены как программой (иерархия типов, например, NoSuchFileException, если вы хотите специально отреагировать на такую ​​​​проблему), так и человеком. , в том, что сообщения об этих исключениях объясняют на английском языке, что не так.

Во-вторых, вы ДОЛЖНЫ безопасно закрывать объекты, представляющие системные ресурсы, а ваш код этого не делает. Есть удобный синтаксис try-with, который упрощает эту задачу, так что давайте сделаем и это!

В-третьих, вы сбрасываете, а затем закрываете. Это бессмысленно; close() уже подразумевает сброс, нет причин вызывать flush() перед закрытием, он просто загромождает ваш код. На самом деле, с помощью try-with вообще не нужно закрывать.

Таким образом:

Path tempFile = Paths.get("temp.txt");
Path saveFile = Paths.get("save.txt");
try (
  Writer fw = Files.newBufferedWriter(tempFile, StandardOpenOption.APPEND);
  BufferedReader br = Files.newBufferedReader(saveFile);
  ) {

  String line;
  while ((line = br.readLine()) != null) {
    if (line.equals(player.username)) continue;
    fw.write(line);
    fw.write("\n");
  }
}

Files.delete(saveFile);
Files.move(tempFile, saveFile);

Спасибо за ответ, но как мне создать новый файл с java.nio.package, потому что я хочу создать новый временный файл, не получая существующий файл temp.txt

nipeng 08.04.2023 19:44

Так же, как вы делаете сегодня. File — это не файл, это структура данных, содержащая представление пути к файлу. Я не вижу сильного принуждения полностью избегать File — просто не вызывайте его методы, которые на самом деле делают что-то с файловой системой. Но обратите внимание, вам не нужен File, чтобы создать FileWriter.

Arfur Narf 08.04.2023 19:47

@ArfurNarf Если вы относитесь к File как к средству для пути и игнорируете практически все его методы, то..... почему бы не использовать String? Или, если вы (правильно) предпочитаете тип, который более подробно описывает то, что он содержит, что может сделать File, чего не может Path, кроме того, что вы не должны делать с File?

rzwitserloot 08.04.2023 19:57

@nipeng Если вам нужен новый временный файл, Files.newBufferedWriter(path, StandardOpenOption.CREATE_NEW) гарантирует, что он новый (выбрасывает, если это не так), и Files.createTempFile создает новые файлы, выбирая для вас случайные имена, чтобы гарантировать их уникальность.

rzwitserloot 08.04.2023 19:58

Хорошо, спасибо за все ответы, которые я пробовал, но используя `Files.createFile(tempFile); ` тоже хорошо. теперь проблема в том, что я получаю файл ошибки, который используется другим процессом, я даже не открывал файл

nipeng 08.04.2023 20:07

Вы уверены? Вероятно, это ваш собственный процесс. Код вашего примера неправильно закрывает ресурсы (используйте синтаксис try(...)).

rzwitserloot 08.04.2023 20:21

Я почти уверен, что уже завершил весь процесс отладки, а также уже использую синтаксис try. Созданный временный файл работает нормально, но выдает file is being used by another process, когда достигает Files.delete.

nipeng 08.04.2023 20:28

@rzwitserloot "тогда..... почему бы не использовать String?" -- В таком случае, почему бы и нет? Я ответил с позиции, что не могу переписать весь огромный корпус кода, с которым мне нужно взаимодействовать. Построение пути только для вызова toFile всегда кажется немного глупым.

Arfur Narf 08.04.2023 23:14

@ArfurNarf Устаревший / устаревший в словарном смысле не означает «выйти и переписать все его использования сейчас». Просто: ответ SO, который советует использовать это сейчас, неверен, и вам не следует писать новый код с этим материалом. Нет ничего плохого в том, чтобы использовать .toPath() / toFile() для обозначения устаревшего API, который еще не принимает объекты Path.

rzwitserloot 09.04.2023 02:05

@nipeng вставьте полный код. Ошибка вам не лжет - она ​​открыта в каком-то процессе. Весьма вероятно, что это ваш код.

rzwitserloot 09.04.2023 02:20

Извините за поздний ответ Вот мой код: Path tempFile = Paths.get("temp.txt"); try { Files.newBufferedWriter(tempFile, StandardOpenOption.CREATE_NEW); } catch (IOException e) { // TODO: handle exception } Path saveFile = Paths.get("save.txt"); Path playerFile = Paths.get(player.username + ".txt"); В остальном тот же код try catch, который вы предоставили

nipeng 09.04.2023 07:11

Я уже разобрался, спасибо

nipeng 09.04.2023 08:52

@nipeng Этот код, который вы только что вставили в комментарий 4 часа назад, не использует try-with, и это именно то, что я вам сказал, является вероятным объяснением. Начните использовать try-with.

rzwitserloot 09.04.2023 11:48

Другие вопросы по теме