为什么FileOutputStream抛出FileNotFoundException?

时间:2013-11-23 12:44:09

标签: java android java-io android-file android-context

Android Developer参考(this page)说:

Throws FileNotFoundException

但在一开始,它说:

  

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

如果是这种情况,为什么会抛出FileNotFoundException?

我只是想确保我正确处理所有案件。我正在使用默认功能,所以我可以将它包装在try..catch块中,catch块中没有任何内容,因为FileNotFoundException无法在默认情况下抛出功能?

编辑“默认功能”的示例:

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

4 个答案:

答案 0 :(得分:9)

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

答案 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目录。

答案 2 :(得分:2)

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

不工作( - &gt; 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之间的“。”而不是“:”)

答案 3 :(得分:1)

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