Проверьте, существует ли файл перед вызовом openFileInput
Чтобы прочитать файл в Android из вашей частной области хранения приложений, вы используете функцию openFileInput()
.
Мой вопрос в том, есть ли способ проверить, существует ли этот файл перед вызовом этой функции? Функция может вызывать FileNotFoundException
, но мне нравится называть это, а затем делать что-то, основанное на try
- catch
, является плохой практикой.
Использование File.exist()
кажется странным для использования, так как для этого потребуется создать экземпляр класса, и я не уверен, что просто передать имя файла ему, чтобы он нашел файл в частной области моего телефон.
Ответы
Ответ 1
public boolean fileExists(Context context, String filename) {
File file = context.getFileStreamPath(filename);
if(file == null || !file.exists()) {
return false;
}
return true;
}
EDIT:
Кроме того, это другой способ для файлов во внешнем хранилище.
String fileUrl = "/appname/data.xml";
String file = android.os.Environment.getExternalStorageDirectory().getPath() + fileUrl;
File f = new File(file);
if(f.exists())
return;
Ответ 2
Функция может быть вызвана через FileNotFoundException, но я чувствую, что это нужно вызывать, а затем делать что-то на основе попытки перехвата - плохая практика.
Я не согласен. ИМО, это проверка, существует ли файл перед открытием, что является плохой практикой. Сравните эти две версии кода:
File f = new File("someFile");
InputStream is;
Версия №1
if (f.exists()) {
is = new FileInputStream(f);
...
} else {
System.err.println("Doesn't exist");
}
Версия № 2
try {
is = new FileInputStream(f);
...
} catch (FileNotFoundException ex) {
System.err.println("Doesn't exist");
}
Существует ряд проблем с первой версией:
Версия # 1 делает дополнительный системный вызов, когда вы звоните f.exists()
. Это делает первую версию медленнее в среднем, если не существует высокой вероятности того, что файл не будет существовать.
Версия № 1 имеет состояние гонки. Если какой-то внешний процесс удаляет файл примерно в одно и то же время, вы можете получить file.exists()
, возвращающий true, а затем конструктор FileInputStream
, выбрасывающий FileNotFoundException
. Это такое состояние гонки, которое можно использовать для нарушения безопасности, если рассматриваемый файл критичен к безопасности.
(На самом деле, есть и второе условие гонки. Если вы вызываете file.exists()
во время создания файла, он может вернуть false
. В этом случае вы напечатаете сообщение об ошибке, даже если new FileInputStream
мог преуспеть. Расовое состояние, вероятно, безвредно.)
Еще одна проблема заключается в том, что FileInputStream
объявлен как бросающий IOException
. Тестирование, чтобы увидеть, существует ли файл, имеет дело только с одним из возможных режимов отказа. В любом случае ваш код будет иметь дело с другим IOException
.
@Pieces прокомментировал:
Исключения должны быть для случаев, когда что-то действительно идет не так, что вы не можете контролировать. В этом случае я полностью контролирую его.
На самом деле, вы не имеете полного контроля над этим. Конечно, не в общем случае. Даже в вашем конкретном случае условия гонки все еще возможны в теории.
Но настоящая проблема с этим типом мышления заключается в том, что вы в конечном итоге перепрыгиваете через обручи, чтобы избежать исключений в ситуациях, когда обработка исключений/исключений является лучшим решением. Это делает код более сложным, менее читаемым, потенциально более медленным и/или более хрупким.
Нормальная догма выглядит так:
"Исключения следует использовать только в исключительных ситуациях".
Это не то же самое, что сказать, что ты сказал. Слово "исключительный" на самом деле просто означает "не нормально". Это имеет гораздо более широкое значение, чем "что-то идет не так, что вы не можете контролировать".
Я склонен расширять догму следующим образом:
Исключения не должны использоваться для нормального управления потоком.
Исключения не следует использовать, если они в среднем окажутся слишком дорогими.
Исключения следует использовать, если тесты, которые вы будете использовать, чтобы избежать их, не являются надежными.
Исключения следует использовать, если тесты, которые вы будете использовать, чтобы избежать их, в среднем слишком дороги.
Исключения следует использовать, если они значительно упрощают ваш код (по модулю выше). И критерий простоты - читаем ли код среднестатистический программист на Java.
(Примечание: "в среднем" и "слишком дорого"...)
Теперь можно спорить, пока коровы не вернутся домой, о том, насколько исключительным должно быть событие, но я полагаю, что это действительно вопрос баланса относительной простоты подходов (в контексте) и средних затрат на производительность (в контексте).). Любое догматическое правило, которое не учитывает компромиссы и контекст, в некоторых случаях может причинить вам вред.
Ответ 3
Эта работа для меня.
try {
FileInputStream fis = openFileInput(String filename);
// ... do something
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
но случается, несколько раз он возвращает исключение, то же самое... работает с adb.