getResourceAsStream返回null

时间:2013-05-15 16:37:02

标签: java file-io resources

我正在我的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中。

我该如何解决这个问题?

20 个答案:

答案 0 :(得分:133)

Lifepaths.class.getClass().getResourceAsStream(...)使用系统类加载器加载资源,它显然失败,因为它看不到你的JAR

Lifepaths.class.getResourceAsStream(...)使用加载Lifepaths类的相同类加载器加载资源,它应该可以访问JAR中的资源

答案 1 :(得分:52)

规则如下:

  1. 检查要在JAR中加载的文件的位置(从而确保它实际添加到JAR中)
  2. 使用绝对路径:路径从JAR的根开始
  3. 使用相对路径:path从您正在调用的类的包目录开始getResource / getResoucreAsStream
  4. 尝试:

    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类加载器将首先使用父类加载器来加载资源: deletegate-parent-classloader

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()。至少你的代码会正确执行。