Maven项目在IDE中读取文件,但无法从JAR文件中读取。

huangapple go评论54阅读模式
英文:

Maven project reads file in IDE but not from JAR

问题

Sure, here's the translated content without the code part:

我编写了一个方法,使用Scanner对象从文件中读取内容(文件名为“test.txt”,位于资源文件夹中),然后返回一个字符串。
当我在IDE中运行项目时,它能够正常工作,并成功返回字符串,但是当我将它编译成JAR文件并从终端运行时,它却返回null,好像没有正确读取文件。
理应发生的情况是它应该返回字符串。

我只在Maven项目中遇到过这个问题。
尚未在没有Maven的情况下测试过,但似乎无论是使用Maven还是IntelliJ编译,都会出现相同的问题。

我不知道为什么会发生这种情况。

英文:

I write a method to use a Scanner object to read from a file (the file name is "test.txt" and it is in the resources folder) and return a String.
When I run the project in the IDE it works fine and the String is returned successfully, but when I compile it to a JAR and run it from the terminal it returns null instead, as if it's not reading the file properly.
What should happen is that it should return the string.

I've only encountered this issue on Maven projects.
Have not tested it without Maven, but it looks like the same issue occurs whether I compile with Maven or IntelliJ

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Objects;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Main mainTest = new Main();
        System.out.println(mainTest.test());
    }

    private String test() {
        File file = new File(Objects.requireNonNull(getClass().getClassLoader().getResource("test.txt")).getPath());

        try (
                Scanner scanner = new Scanner(file)
        ) {
            String line = "";

            while (scanner.hasNextLine()) {
                line = scanner.nextLine();
            }
            return line;
        } catch (FileNotFoundException e) {
            e.getMessage();
        }
        return null;
    }
}

I have no clue why this is happening.

答案1

得分: 1

因为一旦将应用程序打包为一个jar文件,您试图加载的文件变成了一个存储在zip文件内而不是存在于文件系统某处的文件。这是运行环境的一个根本性差异,也是在处理存储在类路径上的文件时经典的陷阱之一。

请改用getClass().getClassLoader().getResourceAsStream(),只要文件存储在与类相同的模块中(在这种情况下是相同的jar文件),它总是有效的。

Scanner有一个构造函数,接受一个InputStream。因此,可以像这样操作:

try(InputStream is = getClass().getClassLoader().getResourceAsStream("test.txt")) {

    Scanner scanner = new Scanner(is);
    // 在这里处理相关操作
}
英文:

Because as soon as you package the application as a jar, the file you are trying to load becomes a file stored inside a zip file rather than a file that exists somewhere on your filesystem. That is a fundamental difference in the runtime environment and one of the classic gotchas when it comes to working with files stored on the classpath.

Use getClass().getClassLoader().getResourceAsStream() instead, that always works as long as the file is stored in the same module where the class is stored (in the same jar, in this case).

Scanner has a constructor which accepts an InputStream. So something like:

try(InputStream is = getClass().getClassLoader().getResourceAsStream("test.txt")) {

    Scanner scanner = new Scanner(is);
    // do things with stuff here
}

huangapple
  • 本文由 发表于 2023年2月23日 21:27:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75545492.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定