为什么FileOutputStream抛出FileNotFoundException?

Android开发人员参考( 本页 )说:

Throws FileNotFoundException 

但是一开始就说:

打开与此Context的应用程序包关联的私有文件以进行写入。 如果文件不存在,则创build该文件。

如果是这样的话, 为什么会抛出FileNotFoundException?

我只是想确保我正确处理所有情况。 我正在使用默认function,所以我可以把它封装在一个try..catch块中,而catch块中什么也不做,因为FileNotFoundException不可能被抛出默认的function。

编辑: “默认function”的例子:

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

Solutions Collecting From Web of "为什么FileOutputStream抛出FileNotFoundException?"

例如,如果您尝试打开文件夹,或者您尝试打开的文件不存在,但是您无权创build文件夹,则可能会发生这种情况。

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"); } 

虽然这看起来不太可能看到Fnfexception,但是,您可以看到它不是线程安全的 ,所以如果某个其他线程正在删除/data/data/com.yourpkg,那么f.getParentFile()仍然会抛出该exception。名称/文件目录。

在我的情况下,原因是该文件的名称是不正确的。 显然,文件名冒号不喜欢。

不工作( – > 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"); [...] 

(差异是SimpleDateFormat中HH,mm和ss之间的“。”而不是“:”)

最常见的原因是中间目录不存在。 FileOutputStream不会创build这些。 它也可能是一个权限问题:整个path存在,但在最终目录中没有创build权限,或者如果实际文件已经存在,则覆盖权限。