Обязательно ли проверять FileExists() перед DeleteFile()?

Некоторое время назад, не помню где, я читал о лучшей практике в delphi.

Вместо этого:

if FileExists(MyFile) then begin
        if not DeleteFile(MyFile) then
                ShowMessage('Unable to delete file');
end;

напишите это:

if not DeleteFile(MyFile) then
        ShowMessage('Unable to delete file');

Каковы плюсы и минусы второго?

в первом методе пользователь вообще не получает никакого сообщения, если файл не существует, поэтому он не знает, был ли он удален или нет. Во втором пользователь всегда будет уведомлен, если удаление не удалось. Итак, что лучше, зависит от того, что вы хотите, чтобы ваши пользователи видели

GuidoG 29.05.2019 09:16

Вот два варианта использования: 1. вы ожидаете, что файл может не существовать, и это не ошибка; 2. файл должен существовать, а если его нет, то получаем ошибку.

zed 29.05.2019 09:18

В первом методе файл может быть предположительно удален другим процессом между проверкой FileExists и вызовом DeleteFile, что делает проверку FileExists избыточной, поскольку вы не можете на нее рассчитывать.

HeartWare 29.05.2019 09:18

@zed: Лучшим способом было бы просто вызвать DeleteFile, а в случае сбоя вызвать GetLastError, чтобы определить, что причина не удалось. Если ERR_FILE_NOT_FOUND вы знаете, что это потому, что файл не существует. если ERR_ACCESS_DENIED, вы знаете, что файл существует, но не можете его удалить (он может быть открыт в другом процессе или помечен как Read/Only). Таким образом, вы можете обрабатывать все варианты использования без каких-либо шансов прийти к неправильному выводу на основе результата недействительного вызова FileExists.

HeartWare 29.05.2019 09:22

@Heartware ERROR_PATH_NOT_FOUND также возможна, я думаю

David Heffernan 29.05.2019 09:50

@DavidHeffernan: Верно... Также может быть несколько других ошибок... Например, «Диск не готов», если файл находился на USB-накопителе, который впоследствии был удален.

HeartWare 29.05.2019 13:39
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
6
214
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

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


Проверка существования файла перед попыткой его удаления не является лучшей практикой. На самом деле это классический антишаблон.

Правильный шаблон — попытаться удалить файл напрямую. Если это не удается, проверьте причину отказа. Это скажет вам, существует ли файл, или удаление не удалось по какой-либо другой причине. В Windows это означает использование функции Win32 API с именем DeleteFile и проверку возвращаемого значения на успешность или неудачу. В случае сбоя звоните GetLastError, чтобы узнать причину сбоя.

Выполнение этого кросс-платформенным способом не совсем тривиально, и я не думаю, что RTL предлагает такую ​​функциональность.


Также стоит отметить, что ваши два блока кода не являются взаимозаменяемыми. У них разное поведение. Первый блок обрабатывает несуществующий файл как успех. Второй трактует это как ошибку. Если вы хотите воспроизвести первое поведение только с одним вызовом функции, вам необходимо различать коды ошибок, как описано выше.

Разве Удалить файл () из SysUtils.pas не является кроссплатформенным?

Arnaud Bouchez 29.05.2019 10:01

@Arnaud да, но различение причин ошибок не является частью этого API, или нет?

David Heffernan 29.05.2019 10:04

Он возвращает логическое значение для успеха или неудачи. ОП не имеет в виду причину ошибки низкого уровня, просто если это удалось или нет.

Arnaud Bouchez 29.05.2019 10:05

@Арно Не совсем так. Код, проверяющий, существует ли файл, считает его несуществующим успешным.

David Heffernan 29.05.2019 10:07

Звонить FileExists() бессмысленно.

Файл может существовать, но не может быть удален - например. если он доступен только для чтения или заблокирован другим процессом. Это не будет быстрее, чем вызвать DeleteFile().

Так что 2-я версия предпочтительнее:

if not DeleteFile(MyFile) then
    ShowMessage('Unable to delete file');

Примечание. DeleteFile() из SysUtils.pas является кроссплатформенным и возвращает логическое значение в случае успеха, поскольку комментарии и некоторые ответы касаются только необработанного вызова API из Windows.pas.

Очень важно отметить, что два рассматриваемых блока кода не являются взаимозаменяемыми. Второй блок, повторяющийся в этом ответе, рассматривает ненайденный файл как ошибку.

David Heffernan 29.05.2019 10:09

Все зависит от того, какое поведение вы хотите. Но когда вы ожидаете удалить файл, но не можете, тогда нет необходимости в файлах. Если вы хотите указать причину сбоя пользователю, для кроссплатформенного решения вы можете использовать FileExists для обнаружения отсутствующего файла по сравнению с существующим файлом, который нельзя удалить...

R. Hoek 31.05.2019 22:43

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