2012-01-15 4 views
19

Чтобы прочитать файл в Android из области хранения вашего приложения, вы используете функцию openFileInput().Проверьте, существует ли файл перед вызовом openFileInput

Мой вопрос в том, есть ли способ проверить, существует ли этот файл перед вызовом этой функции? Функция может вызывать FileNotFoundException, но мне хочется называть это, а затем делать что-то на основе try - catch - это плохая практика.

Использование File.exist() кажется странным для использования, так как это потребует создания экземпляра класса, и я не уверен, что если просто передать имя файла ему, он получит его, чтобы найти файл в личной области моего телефона ,

ответ

44
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; 
+1

Примечание: использование File.exists() таким образом 1) не защищает от всех исключений, 2) оставляет вас открытыми для условий гонки, а 3) делает вас медленнее в программе ... если несуществующие файлы сценарий * вероятно *. –

+1

Я предпочитаю первый метод, так как он сохраняет непрозрачность относительно того, где файл на самом деле – njzk2

29

Функция может через FileNotFoundException, но я чувствую, называя это, а затем сделать что-то на основе попытке поймать это плохая практика.

Я не согласен. IMO, он проверяет, существует ли файл перед открытием, что является плохой практикой. Сравните эти два варианта кода:

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 делает дополнительную сист вызов em, когда вы звоните f.exists(). Это делает первую версию более медленной в среднем, если не существует высокой вероятности того, что файл не будет.

  • Версия №1 имеет состояние гонки. Если какой-то внешний процесс удаляет файл примерно в одно и то же время, вы можете получить file.exists(), возвращающий true, а затем создатель FileInputStream, бросающий FileNotFoundException. Это состояние гонки, которое может быть использовано для взлома защиты, если этот файл является критическим для безопасности. (На самом деле, есть второе условие гонки тоже, где файл создается и file.exists() возвращает ложь, когда последующая попытка открыть удастся. Но это состояние гонки, вероятно, безвредны.)

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


@Pieces прокомментировал:

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

На самом деле, у вас нет полного контроля над ним. Конечно, не в общем случае. Даже в вашем конкретном случае использования, состояние гонки все еще возможно в теории.

Но настоящая проблема с этим мышлением заключается в том, что вы в конечном итоге прыгаете через обручи, чтобы избежать исключений в ситуациях, когда исключения/обработка исключений - это решение best. Это делает код более сложным, менее читаемым и потенциально медленным и/или более хрупким.

Нормальная догма выглядит следующим образом:

«Исключения должны использоваться только в исключительных ситуациях».

Это не то же самое, что сказать то, что вы сказали. Слово «исключительный» на самом деле просто означает «не нормально». Это имеет гораздо более широкий смысл, чем «что-то пошло не так, что вы не контролируете».

Я склонен расширить догмат следующим образом:

  • Исключение не должны быть использован для нормального управления потоком.

  • Исключения не должны быть использованы, если они собираются оказаться слишком дорогим в среднем.

  • Исключения Следует использовать, если тесты, которые вы использовали бы, чтобы избежать их, ненадежны.

  • Исключения должны быть использованы, если тесты вы будете использовать, чтобы избежать их слишком дорого в среднем.

  • Исключения Следует использовать, если они значительно упрощают ваш код (по модулю выше). И критерием простоты является то, читается ли код средним программистом Java.

(Примечание - «в среднем» и «слишком дорого» ...)

Теперь можно утверждать, пока коровы не пришли домой о как исключительная событие должно быть, но я считаю, что на самом деле это вопрос балансировки относительной простоты подходов (в контексте) по сравнению со средними затратами на производительность (в контексте). Любое догматическое правило, которое не учитывает компромиссы и контекст, в некоторых случаях наносит вам вред.

+2

Если файл не существует, возможно, потому, что он впервые открыл приложение, я хочу вызвать функцию, которая его записывает со значениями по умолчанию (возможно, я должен был отметить это в моем вопросе). То, что вы предлагаете, - это то, что я буду рассматривать программированием за исключениями. Исключения должны быть, когда что-то действительно идет вразрез с тем, что вы не контролируете. В этом случае я полностью контролирую его. Обработка исключений все равно будет существовать и сможет регистрировать эти условия гонки, если таковые имеются, и это будет случай, когда я не контролирую ситуацию. – Pieces

+0

Этот ответ является исключительным. ;) Однако в случае, если файл не найден, это не исключение, то есть вы ожидаете, что иногда не будет файла (и, особенно если вы _only_ что-то делаете, когда файл находится _not_), другой ответ на самом деле отвечает вопрос. Вы оба получаете +1. – AlbeyAmakiir

+0

@AlbeyAmakiir - Проблема в том, что решение, предложенное в другом ответе, является ненадежным. –

0

Эта работа для меня.

try { 
    FileInputStream fis = openFileInput(String filename); 
    // ... do something 
try { 
    fis.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    } 
} catch (FileNotFoundException e) { 
    e.printStackTrace(); 
} 

но бывает, несколько раз, он возвращает исключение то же самое ... работает с adb.