调用 openFileInput 之前检查文件是否存在

发布于 2024-12-27 10:38:55 字数 305 浏览 2 评论 0原文

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

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

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

To read a file in Android from your app's private storage area you use the functionopenFileInput().

My question is, is there a way to check if this file exists before calling this function? The function can throw a FileNotFoundException, but I feel like calling this and then doing something based on a try-catch is a bad practice.

Using File.exist() seems like a strange thing to use also since it would require instantiating a class and I am not sure if just passing the name of the file to it would get it to find the file in the private area of my phone.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苏辞 2025-01-03 10:38: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;
public boolean fileExists(Context context, String filename) {    
    File file = context.getFileStreamPath(filename);
    if(file == null || !file.exists()) {
        return false;
    }
    return true;
}

EDIT:

Also, here is another way for files in external storage.

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

if(f.exists())
return;
尤怨 2025-01-03 10:38:55

该函数可以通过 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< /代码>。测试文件是否存在仅处理一种可能的故障模式。无论如何,您的代码都必须处理其他 IOException。


@Pieces 评论道:

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

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

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

正常的教条是这样的:

“异常只能在特殊情况下使用”

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

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

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

  • 如果异常平均而言成本太高,则不应使用异常。

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

  • 如果您用来避免异常的测试平均成本太高,则应使用异常。

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

(注意 - “平均”和“太贵”......而“正常”是主观的。)

现在,人们可以争论有多出色,直到奶牛回家为止一个事件需要如此,但我的看法是,这实际上是一个平衡方法的相对简单性(在上下文中)与平均性能成本(在上下文中)的问题。在某些情况下,任何不考虑权衡和背景的教条规则都会给你带来伤害。

The function can through a FileNotFoundException, but I feel like calling this and then doing something based on a try catch is bad practice.

I disagree. IMO, it is testing if the file exists before opening that is bad practice. Compare these two versions of the code:

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

Version #1

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

Version #2

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

There a number of problems with the first version:

  • Version #1 makes an extra system call when you call f.exists(). This makes the first version slower on average, unless there is a high probability that the file won't exist.

  • Version #1 has a race condition. If some external process deletes the file at roughly the same time, you could end up with file.exists() returning true, and then the FileInputStream constructor throwing FileNotFoundException. This is the kind of race condition that can be exploited to break security if the file in question is security critical.

    (Actually, there's a second race condition too. If you call file.exists() while the file is being created, it may return false. In that case you will print the error message, even though new FileInputStream could have succeeded. This race condition is probably harmless.)

A further problem is that the FileInputStream is declared as throwing IOException. Testing to see if the file exists only deals with one of the possible failure modes. Your code is going to have to deal with the other IOExceptions anyway.


@Pieces commented:

Exceptions should be for when something actually goes wrong that you have no control over. In this case, I have complete control over it.

Actually, you don't have complete control over it. Certainly not in the general case. Even in your particular use case, the race condition is still possible in theory.

But the real problem with this line of thinking is that you end up jumping through hoops to avoid exceptions in situations where exceptions / exception handling are the best solution. This makes the code more complicated, less readable, and potentially slower and/or more fragile.

The normal dogma goes like this:

"Exceptions should only be used in exceptional situations".

This is not the same as saying what you said. The word "exceptional" really just means "not normal". This has a much broader meaning than "something actually goes wrong that you have no control over".

I tend to expand on the dogma as follows:

  • Exceptions should not be used for normal flow control.

  • Exceptions should not be used if they are going to prove too expensive on average.

  • Exceptions should be used if the tests you would use to avoid them are not reliable.

  • Exceptions should be used if the tests you would use to avoid them are too expensive on average.

  • Exceptions should be used if they significantly simplify your code (modulo the above). And the criterion for simplicity is whether the code is readable by an average Java programmer.

(Note - "on average" and "too expensive" ... and that "normal" is subjective.)

Now one can argue until the cows come home about how exceptional an event needs to be, but my take is that this is really a matter of balancing the relative simplicity of the approaches (in the context) versus the average performance costs (in the context). Any dogmatic rule that doesn't account for the trade-offs and the context is going to do you harm in some cases.

素染倾城色 2025-01-03 10:38:55

这对我有用。

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

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

This work for me.

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

but happens, some times, it returns an Exception the same ... working with adb.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文