Некоторое время назад, не помню где, я читал о лучшей практике в 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');
Каковы плюсы и минусы второго?
Вот два варианта использования: 1. вы ожидаете, что файл может не существовать, и это не ошибка; 2. файл должен существовать, а если его нет, то получаем ошибку.
В первом методе файл может быть предположительно удален другим процессом между проверкой FileExists и вызовом DeleteFile, что делает проверку FileExists избыточной, поскольку вы не можете на нее рассчитывать.
@zed: Лучшим способом было бы просто вызвать DeleteFile, а в случае сбоя вызвать GetLastError, чтобы определить, что причина не удалось. Если ERR_FILE_NOT_FOUND вы знаете, что это потому, что файл не существует. если ERR_ACCESS_DENIED, вы знаете, что файл существует, но не можете его удалить (он может быть открыт в другом процессе или помечен как Read/Only). Таким образом, вы можете обрабатывать все варианты использования без каких-либо шансов прийти к неправильному выводу на основе результата недействительного вызова FileExists.
@Heartware ERROR_PATH_NOT_FOUND также возможна, я думаю
@DavidHeffernan: Верно... Также может быть несколько других ошибок... Например, «Диск не готов», если файл находился на USB-накопителе, который впоследствии был удален.
Для ясности я прочитал код в вашем вопросе как желание удалить файл и сообщить об ошибке только в том случае, если файл существует и не может быть удален.
Проверка существования файла перед попыткой его удаления не является лучшей практикой. На самом деле это классический антишаблон.
Правильный шаблон — попытаться удалить файл напрямую. Если это не удается, проверьте причину отказа. Это скажет вам, существует ли файл, или удаление не удалось по какой-либо другой причине. В Windows это означает использование функции Win32 API с именем DeleteFile
и проверку возвращаемого значения на успешность или неудачу. В случае сбоя звоните GetLastError
, чтобы узнать причину сбоя.
Выполнение этого кросс-платформенным способом не совсем тривиально, и я не думаю, что RTL предлагает такую функциональность.
Также стоит отметить, что ваши два блока кода не являются взаимозаменяемыми. У них разное поведение. Первый блок обрабатывает несуществующий файл как успех. Второй трактует это как ошибку. Если вы хотите воспроизвести первое поведение только с одним вызовом функции, вам необходимо различать коды ошибок, как описано выше.
Разве Удалить файл () из SysUtils.pas не является кроссплатформенным?
@Arnaud да, но различение причин ошибок не является частью этого API, или нет?
Он возвращает логическое значение для успеха или неудачи. ОП не имеет в виду причину ошибки низкого уровня, просто если это удалось или нет.
@Арно Не совсем так. Код, проверяющий, существует ли файл, считает его несуществующим успешным.
Звонить FileExists()
бессмысленно.
Файл может существовать, но не может быть удален - например. если он доступен только для чтения или заблокирован другим процессом. Это не будет быстрее, чем вызвать DeleteFile()
.
Так что 2-я версия предпочтительнее:
if not DeleteFile(MyFile) then
ShowMessage('Unable to delete file');
Примечание. DeleteFile()
из SysUtils.pas является кроссплатформенным и возвращает логическое значение в случае успеха, поскольку комментарии и некоторые ответы касаются только необработанного вызова API из Windows.pas.
Очень важно отметить, что два рассматриваемых блока кода не являются взаимозаменяемыми. Второй блок, повторяющийся в этом ответе, рассматривает ненайденный файл как ошибку.
Все зависит от того, какое поведение вы хотите. Но когда вы ожидаете удалить файл, но не можете, тогда нет необходимости в файлах. Если вы хотите указать причину сбоя пользователю, для кроссплатформенного решения вы можете использовать FileExists для обнаружения отсутствующего файла по сравнению с существующим файлом, который нельзя удалить...
в первом методе пользователь вообще не получает никакого сообщения, если файл не существует, поэтому он не знает, был ли он удален или нет. Во втором пользователь всегда будет уведомлен, если удаление не удалось. Итак, что лучше, зависит от того, что вы хотите, чтобы ваши пользователи видели