我正在我的Java项目的已编译JAR中的包中加载一个文本文件。相关目录结构如下:
/src/initialization/Lifepaths.txt
用于加载文件的代码是:
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/initialization/Lifepaths.txt"
"initialization/Lifepaths.txt"
"Lifepaths.txt"
这些都不奏效。到目前为止,关于此主题的I've read numerous questions,但它们都没有帮助 - 通常,他们只是说使用根路径加载文件,我就是我已经做了。那,或者只是从当前目录加载文件(只是加载filename
),我也尝试过。该文件正在具有适当名称的适当位置编译到JAR中。
我该如何解决这个问题?
答案 0 :(得分:133)
Lifepaths.class.getClass().getResourceAsStream(...)
使用系统类加载器加载资源,它显然失败,因为它看不到你的JAR
Lifepaths.class.getResourceAsStream(...)
使用加载Lifepaths类的相同类加载器加载资源,它应该可以访问JAR中的资源
答案 1 :(得分:52)
规则如下:
尝试:
Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")
而不是
Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")
(不确定它是否有所作为,但前者将使用正确的ClassLoader / JAR,而我不确定后者)
答案 2 :(得分:42)
因此,有几种方法可以从jar获取资源,每种方法的语法略有不同,需要以不同的方式指定路径。
我见过的最好的解释是来自JavaWorld的这篇文章。我将在这里总结,但如果你想了解更多,你应该查看这篇文章。
方法
1)ClassLoader.getResourceAsStream()
。
格式:“/” - 分隔名称;没有前导“/”(所有名称都是绝对的)。
示例:this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");
2)Class.getResourceAsStream()
格式:“/” - 分隔名称;前导“/”表示绝对名称;所有其他名称都与班级的包相关
示例:this.getClass().getResourceAsStream("/some/pkg/resource.properties");
答案 3 :(得分:12)
不要使用绝对路径,使它们相对于项目中的“resources”目录。快速而脏的代码,显示目录“resources”中MyTest.txt的内容。
@Test
public void testDefaultResource() {
// can we see default resources
BufferedInputStream result = (BufferedInputStream)
Config.class.getClassLoader().getResourceAsStream("MyTest.txt");
byte [] b = new byte[256];
int val = 0;
String txt = null;
do {
try {
val = result.read(b);
if (val > 0) {
txt += new String(b, 0, val);
}
} catch (IOException e) {
e.printStackTrace();
}
} while (val > -1);
System.out.println(txt);
}
答案 4 :(得分:9)
你可能想尝试这个来获取流,即首先获取url,然后将其作为流打开。
URL url = getClass().getResource("/initialization/Lifepaths.txt");
InputStream strm = url.openStream();
我曾经遇到过类似的问题:Reading txt file from jar fails but reading image works
答案 5 :(得分:7)
您正在使用的ClassLoader似乎存在问题。使用contextClassLoader加载类。这与它是否采用静态/非静态方法无关[/ p>]
>>>mystery = '\U0001f4a9'
>>>mystery
'\U0001f4a9'
......
答案 6 :(得分:2)
不知道是否有帮助,但在我的情况下,我的资源在/ src /文件夹中,并且收到此错误。 然后我将图片移动到bin文件夹,它修复了问题。
答案 7 :(得分:2)
确保您的资源目录(例如“src”)在您的类路径中(确保它是eclipse中构建路径中的源目录)。
确保从主类加载器加载clazz。
然后,要加载src / initialization / Lifepaths.txt,请使用
clazz.getResourceAsStream("/initialization/Lifepaths.txt");
为什么:
clazz.getResourcesAsStream(foo)
在clazz 的类路径中查找foo,相对于中的目录clazz。前导“/”使其从clazz的类路径中的任何目录的根加载。
除非你是某种类型的容器,比如Tomcat,或者直接使用ClassLoaders,否则你可以将eclipse /命令行类路径视为唯一的类加载器类路径。
答案 8 :(得分:1)
我发现自己处于类似的问题。由于我正在使用maven,我需要更新我的pom.xml以包含这样的内容:
...
</dependencies>
<build>
<resources>
<resource>
<directory>/src/main/resources</directory>
</resource>
<resource>
<directory>../src/main/resources</directory>
</resource>
</resources>
<pluginManagement>
...
请注意其中的资源标记以指定该文件夹的位置。如果您有嵌套项目(就像我一样),那么您可能希望从其他区域获取资源,而不仅仅是在您正在使用的模块中。如果您使用类似的配置数据,这有助于减少在每个仓库中保留相同的文件
答案 9 :(得分:1)
您真正需要的是文件的完整绝对classPath。因此,不要猜测,而是尝试找出根目录,然后将文件移动到一个更好的位置,以<.war>文件结构为基础...
URL test1 = getClass().getResource("/");
URL test2 = getClass().getClassLoader().getResource("/");
URL test3 = getClass().getClassLoader().getResource("../");
logger.info(test1.getPath());
logger.info(test2.getPath());
logger.info(test3.getPath());
答案 10 :(得分:1)
如果您正在使用Maven,请确保您的包装是“罐子”而不是“ pom”。
library(data.table)
test = data.table(rn=1:4, V1 = c("TeilA1_a", "TeilA_a", "TeilC1_a", "TeilA_a"), V2 = c("4", "3", "2", "1"))
答案 11 :(得分:1)
粗略地说:
getClass().getResource("/")
〜= Thread.currentThread().getContextClassLoader().getResource(".")
假设您的项目结构如下:
├── src
│ ├── main
│ └── test
│ └── test
│ ├── java
│ │ └── com
│ │ └── github
│ │ └── xyz
│ │ └── proj
│ │ ├── MainTest.java
│ │ └── TestBase.java
│ └── resources
│ └── abcd.txt
└── target
└── test-classes
├── com
└── abcd.txt
// in MainClass.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
答案 12 :(得分:0)
默认的JVM类加载器将首先使用父类加载器来加载资源: 。
Lifepaths.class.getClass()
的类加载器是bootstrap classloader
,因此getResourceAsStream
仅搜索$ JAVA_HOME,而不考虑用户提供的classpath
。显然,Lifepaths.txt不存在。
Lifepaths.class
的类加载器是system classpath classloader
,因此getResourceAsStream
将搜索用户定义的classpath
,并且Lifepaths.txt就在其中。
使用java.lang.Class#getResourceAsStream(String name)
时,将以package name
作为前缀添加不是以'/'开头的名称。如果要避免这种情况,请使用java.lang.ClassLoader#getResourceAsStream
。
例如:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourceName = "Lifepaths.txt";
InputStream resourceStream = loader.getResourceAsStream(resourceName);
答案 13 :(得分:0)
就我而言,除非我从文件名中删除空格,否则一切无济于事...
答案 14 :(得分:0)
对我有用的是在My Project / Java Resources / src下添加文件,然后使用
this.getClass().getClassLoader().getResourceAsStream(myfile.txt);
我不需要明确地将此文件添加到路径中(显然将其添加到/ src)
答案 15 :(得分:0)
对我有用的是我将文件放在下面
src/main/java/myfile.log
和
InputStream is = getClass().getClassLoader().getResourceAsStream("myfile.log");
if (is == null) {
throw new FileNotFoundException("Log file not provided");
}
答案 16 :(得分:0)
请删除
../src/main/resources或包含您要读取的文件
答案 17 :(得分:0)
在 pom.xml 中管理或删除 ../src/main/resources
答案 18 :(得分:0)
我的来电类在src/main/...
是什么帮助我从 src/test/resources/folder/file.properties
加载资源
`properties.load(getClass().getClassLoader().getResourceAsStream("folder/file.properties"));`
https://howtodoinjava.com/java/io/read-file-from-resources-folder/
Java 11
答案 19 :(得分:-12)
@Emracool ......我建议你另类。因为您似乎正在尝试加载* .txt文件。最好使用FileInputStream()
而不是令人讨厌的getClass().getClassLoader().getResourceAsStream()
或getClass().getResourceAsStream()
。至少你的代码会正确执行。