Java 为什么 FileOutputStream 会抛出 FileNotFoundException?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20162447/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 23:36:28  来源:igfitidea点击:

Why does FileOutputStream throw FileNotFoundException?

javaandroidjava-ioandroid-fileandroid-context

提问by 1owk3y

The Android Developer reference (this page) says:

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

Throws FileNotFoundException

But at the very start, it says:

但一开始,它说:

Open a private file associated with this Context's application package for writing. Creates the file if it doesn't already exist.

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

If that is the case, why would the FileNotFoundException ever be thrown?

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

I just want to make sure I'm properly handling all cases. I am using the default functionality, so can I just wrap this in a try..catchblock with nothing in the catchblock since it is not possible for a FileNotFoundExceptionto ever be thrown in the default functionality?

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

Edit:example of 'default functionality':

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

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

采纳答案by Blub

This might happen for example if you try to open a Folder or if the file you try to open does not exist, but you don't have permissions to create it either.

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

回答by Robin

The ContextImpl.openFileOutput is implemented as following on ICS:

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

The function makeFileName will make sure you cannot specify any directory structure here:

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

Although this seems not possibly to see the Fnf exception, however, you can see that it is not thread safe, so f.getParentFile() might still throw that exception if some other thread is removing the /data/data/com.yourpkg.name/files directory.

尽管这似乎不可能看到 Fnf 异常,但是,您可以看到它不是线程安全的,因此如果其他线程正在删除 /data/data/com.yourpkg,f.getParentFile() 可能仍会抛出该异常。名称/文件目录。

回答by user207421

The most common cause is that an intermediate directory doesn't exist. FileOutputStreamwon't create those. It can also be a permissions problem: the entire path exists but you don't have create permissions in the final directory, or overwrite permissions on the actual file if it already exists.

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

回答by masand

In my case the reason was that the name of the file was not OK. Obviously, colons in the filename are disliked.

就我而言,原因是文件名不正确。显然,文件名中的冒号是不受欢迎的。

Not working (-> FileNotFoundException):

不工作(-> 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);

Working:

在职的:

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

(Difference is the "." instead of ":" between HH, mm and ss in the SimpleDateFormat)

(区别在于 SimpleDateFormat 中 HH、mm 和 ss 之间的“.”而不是“:”)