Java 为什么FileOutputStream抛出FileNotFoundException?

Java 为什么FileOutputStream抛出FileNotFoundException?,java,android,java-io,android-file,android-context,Java,Android,Java Io,Android File,Android Context,Android开发者参考()说: 但一开始,它说: 打开与此上下文的应用程序包关联的私有文件进行写入如果文件不存在,则创建该文件。 如果是这样,为什么会抛出FileNotFoundException? 我只是想确保我妥善处理了所有案件。我正在使用默认功能,因此我可以将其包装在try..catch块中,而catch块中没有任何内容,因为默认功能中不可能抛出FileNotFoundException 编辑:默认功能示例: String FILENAME = "hello_file"; String

Android开发者参考()说:

但一开始,它说:

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

如果是这样,为什么会抛出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();

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

在ICS上,ContextImpl.openFileOutput的实现如下所示:

@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");
    }
private File makeFilename(文件基,字符串名){
if(name.indexOf(File.separatorChar)<0){
返回新文件(基、名称);
}
抛出新的IllegalArgumentException(
“文件”+name+“包含路径分隔符”);
}

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

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

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

不工作(->FileNotFoundException):

工作:

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

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

您的应用程序是否有可能没有权限在您指向的位置创建文件?@Pshemo我应该指出,我实际上并没有得到异常,只是准备在另一台设备上抛出它。但是文件夹权限是一个非常有效的点(虽然它不应该是根目录上的问题,对吗?)我看到了“附加模式”的引用,这不是默认功能,但是感谢您演示了一个例外可以通过的案例Boda的答案真的是您所说的案例吗?是的,因为缺少源文件夹也可能导致问题,他的答案最有可能与提出此问题的其他人相关。不过,我借此机会感谢您在回答中所做的大量深入研究。奇怪的是,创建父目录而不是祖父母等目录很麻烦。Android希望将您的所有“杂项”文件限制为存储在包目录的“文件”文件夹中。这似乎是最可能的情况将抛出异常的位置;谢谢你的回答,这是有道理的,尽管例外名称的选择非常糟糕“不存在”正确,但“但您也没有创建它的权限”不正确
FileOutputStream
不尝试创建目录。您正在使用通用Linux,对于这种特殊的Android“文件”文件夹,“文件”文件夹通常由框架API创建。因此,当用户故意手动创建“文件”文件夹而未分配写入权限时,就会出现您答案中提到的情况?@Rohan我说的是通用操作系统。“Linux”一词没有出现在我的回答中,它同样适用于Unix、Windows、AIX、HP-UX、Solaris、MS.DOS、OS/2、IX/370和任何数量的其他系统。我已经在最终目录中解决了权限问题。谢谢!“,”而不是“:”是我要找的!
    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");
    [...]