【问题标题】:Check if a file exists before calling openFileInput在调用 openFileInput 之前检查文件是否存在
【发布时间】:2012-02-10 15:30:11
【问题描述】:

要从应用的私有存储区读取 Android 中的文件,请使用函数openFileInput()

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

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

【问题讨论】:

    标签: java android file file-exists


    【解决方案1】:

    该函数可以通过 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");
    }
    

    第一个版本有很多问题:

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

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

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

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


    @Pieces 评论:

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

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

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

    正常的教条是这样的:

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

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

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

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

    • 不应使用例外,如果它们将被证明过于昂贵平均而言

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

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

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

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

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

    【讨论】:

      【解决方案2】:

      这对我有用。

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

      但有时,它会返回一个相同的异常......与 adb 一起工作。

      【讨论】:

        【解决方案3】:
        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;
        

        【讨论】:

        • 注意:以这种方式使用 File.exists() 1) 不能防止所有异常,2) 让您对竞争条件保持开放,以及 3) 平均而言会使您的编程速度变慢...除非不存在的文件是可能的情况。
        • 我更喜欢第一种方法,因为它保持文件实际位置的不透明度
        猜你喜欢
        • 2019-03-07
        • 1970-01-01
        • 2018-02-20
        • 2013-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-22
        • 2016-02-10
        相关资源
        最近更新 更多