如果我不首先抛出 FileNotFoundExcetion,为啥 file.exists() 总是返回 true

Posted

技术标签:

【中文标题】如果我不首先抛出 FileNotFoundExcetion,为啥 file.exists() 总是返回 true【英文标题】:Why does file.exists() always return true if I don't throw FileNotFoundExcetion in the first place如果我不首先抛出 FileNotFoundExcetion,为什么 file.exists() 总是返回 true 【发布时间】:2016-11-28 02:38:37 【问题描述】:
public class Main 

final private static int MAX_RECORD_NUMBER = 20;
final private static int RECORD_LENGTH = 71;

public static void main(String[] args) throws IOException, FileNotFoundException
    Scanner input = new Scanner(System.in);
    System.out.println("Please input the file location and name.");
    String filepath = input.next();
    File file = new File(filepath); 

    boolean isExisted = file.exists(); // Problem exists here if I delete FileNotFoundException

    RandomAccessFile store = new RandomAccessFile(file, "rw");

    if (!isExisted) 
        String dummy = "Empty record                                                           ";
        for (int i = 0; i < MAX_RECORD_NUMBER; i++) 
            store.writeUTF(dummy);
        
    

我在这里遇到了一个小故障。如果我没有抛出 FileNotFoundException,file.exists() 方法将总是返回 true(即使文件真的不存在)。在这种情况下,如果我不在 main 方法的开头抛出 FileNotFoundException,它就无法将 UTF 写入该文件。这一定是一个愚蠢的问题,但我只想知道这背后的机制是什么。 API 对我也没有帮助。我非常感谢任何可以向我解释的人。

编辑:对不起,我之前不清楚。我真正想问的是,为什么 .exists() 方法总是返回 true 而不是 false 或其他意外错误?

【问题讨论】:

你了解检查异常的概念吗? @Dici 是的。所以这都是关于检查异常的吗?我想如果我不抛出检查异常,日食不会让我通过。但是我在编码时没有显示任何错误。 您的问题的标题需要改写。请记住,您写的每一个问题都是针对未来的人(以及您)。 如果没有throws 子句,您的代码将无法编译,但您的问题似乎告诉我您对这些概念有点不清楚 @PhantomPain FileNotFoundException 扩展 IOException 【参考方案1】:

您需要了解引发此异常的位置。而地方就是这一行:

RandomAccessFile store = new RandomAccessFile(file, "rw");

看看FileNotFoundException的API,你就会知道它在RandomAccessFile构造函数中正如预期的那样被抛出。

使用以下代码在没有 RandomAccessFile 的情况下测试您的逻辑:

import java.io.*;
import java.util.Scanner;

public class Main 

    public static void main(String[] args)
        Scanner input = new Scanner(System.in);
        System.out.println("Please input the file location and name.");
        String filepath = input.next();
        File file = new File(filepath); 
        if (file.exists()) System.out.println("EXISTS!"); else System.out.println("DOESN'T EXIST!");
    


现在问题的第一部分应该很清楚了。函数file.exists() 工作正常。逻辑上的缺陷来自这样一个事实,即 RandomAccessFile 构造函数能够创建文件,但并非总是如此。这就是为什么您需要为异常提供服务。以下是 Java 8 API 构造函数的摘录:

FileNotFoundException - 如果模式为“r”但给定的文件对象不表示现有的常规文件,或者如果模式以“rw”开头但给定的文件对象不表示现有的可写常规文件文件和该名称的新常规文件无法创建,或者在打开或创建文件时出现其他错误

所以您的代码的另一部分可能如下所示:

try 
    RandomAccessFile store = new RandomAccessFile(file, "rw");
    String dummy = "Empty record                                                           ";
    for (int i = 0; i < MAX_RECORD_NUMBER; i++) 
       store.writeUTF(dummy);
    
 catch (FileNotFoundException e)
    System.err.println("File cannot be created!");

但这还不够,关于异常服务,因为您在这里使用了writeUTF(dummy) 函数。这个函数抛出:

IOException - 如果发生 I/O 错误。(正如 RandomAccessFile 的 API 所说。)

因此,您需要处理 IOException。例如,在现有的一个 catch 子句上再附加一个,这个:

catch (IOException e)
    System.err.println("Couldn't write to file!");
 

或者您可以跳过 FileNotFoundException,因为它是 IOException 的子类并且只有一个带有 IOException 的 catch 子句。但是,正如您所见,很明显它们代表两种不同的原因。

所以最终你的课程看起来像这样:

import java.io.*;
import java.util.Scanner;

public class Main 

final private static int MAX_RECORD_NUMBER = 20;
final private static int RECORD_LENGTH = 71;

    public static void main(String[] args)
        Scanner input = new Scanner(System.in);
        System.out.println("Please input the file location and name.");
        String filepath = input.next();
        File file = new File(filepath); 
        //if (file.exists()) System.out.println("EXISTS!"); else System.out.println("DOESN'T EXIST!");

        try 
            RandomAccessFile store = new RandomAccessFile(file, "rw");
            String dummy = "Empty record                                                           ";
            for (int i = 0; i < MAX_RECORD_NUMBER; i++) 
               store.writeUTF(dummy);
            
         catch (FileNotFoundException e)
            System.err.println("File cannot be created!");
         catch (IOException e)
            System.err.println("Couldn't write to file!");
        
    

有些部分是不需要的。分析我的解决方案,它应该可以澄清你的错误。或者问我更多。无论如何,这个答案有点冗长。

最后一点。其他线程中的人对类似的事情感到困惑。您可以在右侧看到指向它们的链接。长话短说,使用文件的完整路径。如需更多详细信息,请查看链接。

【讨论】:

你已经清楚地发现了他逻辑中的错误,但你并没有真正回答。不要让他猜到答案,想想你答案的后来读者。当你编辑你的问题时,我会投票赞成:) 现在应该很清楚了。或者我没有看到问题的一部分。 好的,我现在看到另一部分了。 我现在明白了,谢谢。剩下一件事,为什么它总是用IOException 而没有FileNotFoundException 返回true?这是这里的重要部分:D 我的意思是你的解决方案也应该提出一个修复,而不是一个 sn-p 来演示这个错误【参考方案2】:

这是直接来自Java API:

java.io.FileNotFoundException

This exception will be thrown by [...] when a file with the specified pathname does not exist. 

所以你可以包围

RandomAccessFile store = new RandomAccessFile(file, "rw");

使用这样的 try-catch 块:

Scanner input = new Scanner(System.in);
System.out.println("Please input the file location and name.");
String filepath = input.next();
File file = new File(filepath); 
boolean isExisted = file.exists(); 

try

    RandomAccessFile store = new RandomAccessFile(file, "rw");

    if (!isExisted) 
        String dummy = "Empty record                                                           ";
        for (int i = 0; i < MAX_RECORD_NUMBER; i++) 
            store.writeUTF(dummy);
        
    
catch (FileNotFoundException e)
    System.err.println("File not found!");
    e.printStackTrace();
catch (IOException e)
    System.err.println("Couldn't write to/read file!");
    e.printStackTrace();

这样,如果出现问题(用户输入了错误的路径/用户无权读取/写入文件),您可以处理错误而不是程序崩溃。有关 try-catch 块的更多信息,请查看here。

【讨论】:

他不需要来捕捉异常。他也可以传播它,他已经这样做了 当然他可以在打开文件之前检查是否存在,这将替换捕获,但他没有检查以确定他是否有权读取/写入文件,即使它存在. 我只是说他可以在throws 子句中添加例外(我不是反对者) 但是他无法正确处理它,他的程序即将崩溃。 Try-catch 的存在是有原因 已检查的异常也存在是有原因的:D 有时崩溃是正确的做法。我只是不希望你的回答给人的印象是只有一种方法可以处理已检查的异常

以上是关于如果我不首先抛出 FileNotFoundExcetion,为啥 file.exists() 总是返回 true的主要内容,如果未能解决你的问题,请参考以下文章

FileNotFoundException 有时会被抛出,我不知道为啥

如果组合框为空,combobox.removeAllItems 方法会抛出异常吗? [关闭]

MySql - 如果表存在,只更新一些行 - 不希望抛出错误

PinvokeStackImbalance 发生。抛出此异常,但我不知道错误是啥?

我不明白为啥会抛出“调用未定义的方法 CI_Input()::event()”

添加javax.servlet-api依赖项抛出org.slf4j.impl.StaticLoggerBinder无法加载但我不使用sl4j的异常,我使用百万美元