27

要从应用程序的私有存储区域读取 Android 中的文件,您可以使用openFileInput().

我的问题是,有没有办法在调用这个函数之前检查这个文件是否存在?该函数可以抛出 a FileNotFoundException,但我觉得调用它然后基于 a try-做一些事情catch是一种不好的做法。

使用File.exist()似乎也是一件奇怪的事情,因为它需要实例化一个类,而且我不确定只是将文件名传递给它是否会让它在我手机的私人区域中找到文件。

4

3 回答 3

55
public boolean fileExists(Context context, String filename) {    
    File file = context.getFileStreamPath(filename);
    if(file == null || !file.exists()) {
        return false;
    }
    return true;
}

编辑:

此外,这是外部存储中文件的另一种方式。

String fileUrl = "/appname/data.xml";
String file = android.os.Environment.getExternalStorageDirectory().getPath() + fileUrl;
File f = new File(file);

if(f.exists())
return;
于 2012-01-15T03:35:24.253 回答
32

该函数可以通过 FileNotFoundException,但我觉得调用它然后基于 try catch 执行某些操作是不好的做法。

我不同意。IMO,它正在测试文件在打开之前是否存在,这是不好的做法。比较这两个版本的代码:

File f = new File("someFile");
InputStream is;

版本 #1

if (f.exists()) {
    is = new FileInputStream(f);
    ...
} else {
    System.err.println("Doesn't exist");
}

版本 #2

try {
    is = new FileInputStream(f);
    ...
} catch (FileNotFoundException ex) {
    System.err.println("Doesn't exist");
}

第一个版本有很多问题:

  • 版本 #1 在您调用f.exists(). 这使得第一个版本平均变慢,除非文件不存在的可能性很高。

  • 版本 #1 有一个竞争条件。如果某个外部进程大致同时删除了该文件,您最终可能会file.exists()返回 true,然后FileInputStream构造函数会抛出FileNotFoundException. 如果所讨论的文件对安全性至关重要,则可以利用这种竞争条件来破坏安全性。

    (实际上,还有第二个竞争条件。如果您file.exists()在创建文件时调用,它可能会返回false。在这种情况下,您将打印错误消息,即使new FileInputStream可能已经成功。这种竞争条件可能是无害的。)

另一个问题是FileInputStream被声明为 throwing IOException。测试文件是否存在只处理一种可能的故障模式。IOException无论如何,您的代码将不得不处理其他代码。


@Pieces 评论道:

例外情况应该是当您无法控制的实际出现问题时。在这种情况下,我可以完全控制它。

实际上,您无法完全控制它。在一般情况下当然不是。即使在您的特定用例中,竞争条件在理论上仍然是可能的。

但是这种思路的真正问题是,在异常/异常处理是最佳解决方案的情况下,您最终会跳过障碍来避免异常。这使得代码更复杂、可读性更低,并且可能更慢和/或更脆弱。

正常的教条是这样的:

“例外只应在特殊情况下使用”

这和你说的不一样。“异常”这个词实际上只是意味着“不正常”。这比“您无法控制的实际出现问题”具有更广泛的含义。

我倾向于将教条扩展如下:

  • 异常应用于正常的流控制。

  • 如果它们将被证明平均成本太高,则不应使用例外。

  • 如果您用来避免异常的测试不可靠,则应使用异常。

  • 如果您用来避免它们的测试平均而言过于昂贵,则应该使用异常。

  • 如果异常显着简化了您的代码(以上述为模),则应使用异常。简单的标准是代码是否可以被普通 Java 程序员阅读。

(注意 - “平均”和“太贵”......)

现在人们可以争论,直到奶牛们回家,关于一个事件需要多么特殊,但我的看法是,这实际上是一个平衡方法的相对简单性(在上下文中)与平均性能成本(在上下文中)的问题)。在某些情况下,任何不考虑权衡和上下文的教条规则都会对您造成伤害。

于 2012-01-15T07:13:40.260 回答
0

这对我有用。

try {
  FileInputStream fis = openFileInput(String filename);
  // ... do something
try {
    fis.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
} catch (FileNotFoundException e) { 
  e.printStackTrace();
}

但是有时会发生相同的异常...与adb一起使用。

于 2016-02-29T16:55:41.297 回答