我正在从我的Java项目的编译JAR中的包中加载一个文本文件。相关目录结构如下:
/src/initialization/Lifepaths.txt
我的代码通过调用Class::getResourceAsStream来返回一个InputStream来加载一个文件。
public class Lifepaths {
public static void execute() {
System.out.println(Lifepaths.class.getClass().
getResourceAsStream("/initialization/Lifepaths.txt"));
}
private Lifepaths() {}
//This is temporary; will eventually be called from outside
public static void main(String[] args) {execute();}
}
不管我用什么,输出总是输出null。我不知道为什么上面的方法不管用,所以我也尝试了一下:
“初始化/ src / / Lifepaths.txt”
“初始化/ Lifepaths.txt”
“Lifepaths.txt”
这两种方法都不起作用。到目前为止,我已经阅读了许多关于这个主题的问题,但没有一个是有帮助的——通常,他们只是说使用根路径加载文件,而我已经这样做了。或者只是从当前目录加载文件(只是加载文件名),我也尝试过。该文件将被编译到JAR中的适当位置,并具有适当的名称。
我怎么解决这个问题?
粗略地说:
getClass(). getresource ("/") ~= Thread.currentThread(). getcontextclassloader (). getresource (".")
假设你的项目结构如下:
├── src
│ ├── main
│ └── test
│ ├── java
│ │ └── com
│ │ └── github
│ │ └── xyz
│ │ └── proj
│ │ ├── MainTest.java
│ │ └── TestBase.java
│ └── resources
│ └── abcd.txt
└── target
└── test-classes <-- this.getClass.getResource("/")
│ `--Thread.currentThread().getContextClassLoader().getResources(".")
├── com
│ └── github
│ └── xyz
│ └── proj <-- this.getClass.getResource(".")
│ ├── MainTest.class
│ └── TestBase.class
└── resources
└── abcd.txt
// in MainTest.java
this.getClass.getResource("/") -> "~/proj_dir/target/test-classes/"
this.getClass.getResource(".") -> "~/proj_dir/target/test-classes/com/github/xyz/proj/"
Thread.currentThread().getContextClassLoader().getResources(".") -> "~/proj_dir/target/test-classes/"
Thread.currentThread().getContextClassLoader().getResources("/") -> null
粗略地说:
getClass(). getresource ("/") ~= Thread.currentThread(). getcontextclassloader (). getresource (".")
假设你的项目结构如下:
├── src
│ ├── main
│ └── test
│ ├── java
│ │ └── com
│ │ └── github
│ │ └── xyz
│ │ └── proj
│ │ ├── MainTest.java
│ │ └── TestBase.java
│ └── resources
│ └── abcd.txt
└── target
└── test-classes <-- this.getClass.getResource("/")
│ `--Thread.currentThread().getContextClassLoader().getResources(".")
├── com
│ └── github
│ └── xyz
│ └── proj <-- this.getClass.getResource(".")
│ ├── MainTest.class
│ └── TestBase.class
└── resources
└── abcd.txt
// in MainTest.java
this.getClass.getResource("/") -> "~/proj_dir/target/test-classes/"
this.getClass.getResource(".") -> "~/proj_dir/target/test-classes/com/github/xyz/proj/"
Thread.currentThread().getContextClassLoader().getResources(".") -> "~/proj_dir/target/test-classes/"
Thread.currentThread().getContextClassLoader().getResources("/") -> null
虽然不是一个答案,但我把这个建议作为一个答案,这样我就可以把截图放进去。
对于那些在Windows平台上开发的人,我强烈推荐Microsoft实用程序ProcMon,或进程监视器。
Process Monitor是微软提供的一套实用程序中的一个实用程序(甚至不需要登录就可以下载)。它们都可以在sysinternals.com上获得,sysinternals.com是微软收购并保留的原始主机。
Process Monitor可以监视与任何正在运行的进程相关的大量事件。如果指定File Open事件并提供文件名(或文件名的一部分),它将记录哪个进程试图打开该文件,并显示搜索的每个目录。当您不知道正在运行的代码在哪里寻找您在源/配置中指定的文件时,这可能很有用。
这里有一个例子:
这里我正在寻找(并没有找到)一个模式文件(XSD),以便代码可以使用它来验证一些用户提供的XML。