2013-11-23 3 views
8

Ссылка для разработчиков Android (this page) говорит:Почему FileOutputStream бросает FileNotFoundException?

Throws FileNotFoundException 

Но в самом начале, он говорит:

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

Если это так, то почему бы FileNotFoundException никогда не будет выброшен?

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

Edit: пример «функциональность по умолчанию»:

String FILENAME = "hello_file"; 
String string = "hello world!"; 
FileOutputStream fos = context.openFileOutput(FILENAME, Context.MODE_PRIVATE); 
fos.write(string.getBytes()); 
fos.close(); 
+0

Возможно ли, что у вашего приложения не будет разрешения на создание файла, на который вы указываете? – Pshemo

+0

@Pshemo Я должен указать, я на самом деле не * получаю * Исключение, просто готовясь к возможности его бросить на другое устройство.Но разрешение на папку - очень действительная точка (хотя это не должно быть проблемой для корневого каталога, не так ли?) – 1owk3y

ответ

7

Это может произойти, например, если вы пытаетесь открыть папку или если файл вы пытаетесь открыть, не существует, но вы не» t есть разрешения для его создания.

+0

Это похоже на наиболее вероятную ситуацию, когда будет выбрано Exception; спасибо за ваш ответ – 1owk3y

+1

Имеет смысл, хотя невероятно плохой выбор имени исключения! –

3

ContextImpl.openFileOutput реализуется следующим образом на ICS:

@Override 
public FileOutputStream openFileOutput(String name, int mode) 
    throws FileNotFoundException { 
    final boolean append = (mode&MODE_APPEND) != 0; 
    File f = makeFilename(getFilesDir(), name); 
    try { 
     FileOutputStream fos = new FileOutputStream(f, append); 
     setFilePermissionsFromMode(f.getPath(), mode, 0); 
     return fos; 
    } catch (FileNotFoundException e) { 
    } 

    File parent = f.getParentFile(); 
    parent.mkdir(); 
    FileUtils.setPermissions(
     parent.getPath(), 
     FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 
     -1, -1); 
    FileOutputStream fos = new FileOutputStream(f, append); 
    setFilePermissionsFromMode(f.getPath(), mode, 0); 
    return fos; 
} 

Функция makeFileName будет убедиться, что вы не можете указать любую структуру каталогов здесь:

private File makeFilename(File base, String name) { 
     if (name.indexOf(File.separatorChar) < 0) { 
      return new File(base, name); 
     } 
     throw new IllegalArgumentException(
       "File " + name + " contains a path separator"); 
    } 

Хотя это, кажется, не возможно, чтобы увидеть исключение Fnf, однако, вы можете видеть, что это не потокобезопасный, поэтому f.getParentFile() может все еще выдавать это исключение, если какой-либо другой поток удаляет /data/data/com.yourpkg.name/files di приходской.

+0

Я вижу ссылки на «режим присоединения», который не является функциональностью по умолчанию, однако спасибо за иллюстрацию случая, когда исключение может быть выброшено – 1owk3y

+0

Действительно ли ответ Боды в том случае, о котором вы говорите? – Robin

+0

Да, поскольку недостающая исходная папка может также вызвать проблему, и его ответ наиболее вероятен и релевантен для всех, кто поднимает этот вопрос. Я пользуюсь этой возможностью, однако, чтобы поблагодарить вас за объем глубины и исследований, которые вы вложили в ответ – 1owk3y

1

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

+1

Вы говорите об универсальном Linux, для этого специального случая для файлов с файлами Android, папка «файлы» обычно создается фреймворками API. Итак, ситуация, упомянутая в вашем ответе, произойдет, когда пользователь намеренно вручную создаст папку «файл», не назначая права на запись? – Robin

+1

@Rohan Я говорю об общих операционных системах. Слово «Linux» не появляется в моем ответе, что в равной степени относится к Unix, Windows, AIX, HP-UX, Solaris, MS.DOS, OS/2, IX/370 и к любому числу других систем. Я уже рассмотрел вопрос о разрешениях в конечном каталоге. – EJP

2

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

Не работает (-> FileNotFoundException):

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.SSS"); 
    String fileName = simpleDateFormat.format(new Date()); 
    FileOutputStream fileOutputStream = new FileOutputStream(new File(context.getFilesDir(), fileName), false); 

работы:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss.SSS"); 
    [...] 

("" Разница является вместо ":" между HH, мм и сс в SimpleDateFormat)

+0

Спасибо! "" вместо «:» это то, что я искал! – Inoy

Смежные вопросы