maven: java.io.FileNotFoundException 当尝试使用 Intellij 从资源中打开文件或使用 java 命令与 jar

maven: java.io.FileNotFoundException when trying to open file from resources with Intellij or using java command with jar

我已经将 "Java 8 In Action" 一书中的 github's 项目导入了 intellij 作为 maven 项目。

模块结构如下:

然后,我直接从 Intellij 执行 ExecuteAround class 中的 Main 方法(右键单击 -> 执行 main...)

public static void main(String ...args) throws IOException{

    // method we want to refactor to make more flexible
    String result = processFileLimited();
    System.out.println(result);

    System.out.println("---");

    String oneLine = processFile((BufferedReader b) -> b.readLine());
    System.out.println(oneLine);

    String twoLines = processFile((BufferedReader b) -> b.readLine() + b.readLine());
    System.out.println(twoLines);

}

public static String processFileLimited() throws IOException {
    try (BufferedReader br =
                 new BufferedReader(new FileReader("lambdasinaction/chap3/data.txt"))) {
        return br.readLine();
    }
}


public static String processFile(BufferedReaderProcessor p) throws IOException {
    try(BufferedReader br = new BufferedReader(new FileReader("lambdasinaction/chap3/data.txt"))){
        return p.process(br);
    }

}

public interface BufferedReaderProcessor{
    public String process(BufferedReader b) throws IOException;

}

然后,我得到一个 FileNotFoundException:

Exception in thread "main" java.io.FileNotFoundException: lambdasinaction\chap3\data.txt

如果执行 "maven package",在 jar 中,data.txt 文件直接包含在 chap3 folder/package 中,但是如果我执行,我会得到同样的错误:

java -classpath lambdasinaction-1.0.jar lambdasinaction.chap3.executeAround
Exception in thread "main" java.io.FileNotFoundException: lambdasinaction\chap3\data.txt (Le chemin d?accès spécifié est introuvable)
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(Unknown Source)
        at java.io.FileInputStream.<init>(Unknown Source)
        at java.io.FileInputStream.<init>(Unknown Source)
        at java.io.FileReader.<init>(Unknown Source)
        at lambdasinaction.chap3.ExecuteAround.processFileLimited(ExecuteAround.java:23)
        at lambdasinaction.chap3.ExecuteAround.main(ExecuteAround.java:9)

1- 为什么不是 运行 直接来自 intellij?该文件正确地位于资源文件夹中。

2 - 这可能是最重要的:为什么直接从命令行执行程序时不是 运行?

感谢您的帮助

使用"src/main/resources/lambdasinaction/chap3/data.txt"代替"lambdasinaction/chap3/data.txt"

当您执行 Java 程序时,lambdasinaction/chap3/data.txt 等相对文件名会根据当前工作目录进行解析:

  • 当您使用 Intellij 默认设置启动程序时,当前目录是包含 .idea 文件夹的目录(还包含 pom.xml*.iml*.ipr、等等)
  • 当使用命令行时,可以使用 Linux 上的 pwd 和 Windows
  • 上的 cd 打印出当前目录

文件放在 src/main/resources 下,因此除非当前目录是 resources,否则您将始终获得 FileNotFoundException。部署后您的程序可能找不到您的资源。

好消息是该目录对于 Maven 和 Maven 兼容工具(如 Intellij)来说是特殊的,因为内容可作为类路径资源使用 - 这意味着您将始终能够使用

读取这些文件
getClass().getResourceAsStream("/lambdasinaction/chap3/data.txt");

注意:我没有使用文件系统 (FileReader) 来解析文件名,而是使用(绝对)类路径资源标识符。