通过getClass().getResource()加载文件

15 浏览
0 Comments

通过getClass().getResource()加载文件

我使用getClass.getResource(path)的方式来加载资源文件。代码片段如下:

String url = "Test.properties";
System.out.println("Before printing paths..");
System.out.println("Path2: "+ getClass().getResource(url).getPath());
FileInputStream inputStream = new FileInputStream(new File(getClass().getResource(url).toURI()));
i_propConfig.load(inputStream);
inputStream.close();

在Eclipse中,我已经按照以下层次结构进行了配置(在源代码下有一个名为SwingDemo的文件夹,其中包含我的java文件和资源文件)...

  1. src

    • SwingDemo

      1. CustomDialog.java
      2. Test.properties

当我在Eclipse中运行时,一切都运行正常。但是一旦我尝试从命令行运行应用程序,就会出现空指针异常。

命令行部署的层次结构如下:

文件夹:D:\Work\Java Progrms\SwingDemo

层次结构:

  1. SwingDemo

    • CustomDialog.java
    • Test.properties

首先,我在命令行中的SwingDemo文件夹中编译了这个文件(javac CustomDialog.java)。然后,我回到Java Programs文件夹(因为我在.java类中提到了包),并使用著名的命令运行应用程序

java SwingDemo.CustomDialog

以前,当我使用new FileInputStream("path")时,我也遵循类似的步骤。

按照这种方式进行后,我得到了空指针异常。

我认为getClass().getResource(url)无法从特定目录加载文件。这就是为什么我把资源文件放在与我的java文件相同的目录中。在Eclipse中它运行得很好。但是为什么在从命令行运行时会出错呢?

0
0 Comments

问题的出现原因是在jar文件中访问资源文件时,使用了错误的方法getClass().getResource()。解决方法是使用InputStream通过getResourceAsStream()方法来访问资源文件,并且如果需要将资源文件作为文件实例,则可以将资源文件作为流复制到临时文件中。

具体的解决方法如下所示:

public static File getResourceAsFile(String resourcePath) {
    try {
        InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(resourcePath);
        if (in == null) {
            return null;
        }
        File tempFile = File.createTempFile(String.valueOf(in.hashCode()), ".tmp");
        tempFile.deleteOnExit();
        try (FileOutputStream out = new FileOutputStream(tempFile)) {
            //copy stream
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
        return tempFile;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

这个方法非常有用,可以通过将资源文件作为流复制到临时文件中来访问资源文件。如果需要读取并更新一个json文件,可以使用这个方法来实现。另外,需要注意的是,应该关闭in流。

这个答案应该被标记为接受的答案,因为它在创建一个Kotlin项目的jar文件时,帮助我处理了一个文件的问题。

0
0 Comments

问题的原因是getClass().getResource()方法使用类加载器来加载资源,这意味着资源必须在类路径下才能被加载。在使用Eclipse时,所有放在源文件夹中的内容都会被Eclipse编译:

  • .java文件会被编译成.class文件并放在bin目录下(默认情况下)
  • 其他文件会被复制到bin目录下(保持包/文件夹层次结构)
  • 在使用Eclipse运行程序时,bin目录位于类路径中,因此包含Test.properties文件,这个文件可以通过类加载器使用getResource()getResourceAsStream()来加载。

    如果无法从命令行中工作,那是因为文件不在类路径中。

    需要注意的是,不应该使用FileInputStream inputStream = new FileInputStream(new File(getClass().getResource(url).toURI()));来加载资源。因为这种方式只适用于从文件系统加载文件的情况。如果将应用程序打包成jar文件,或者通过网络加载类,这种方式将无法工作。要获取一个InputStream,只需使用getClass().getResourceAsStream("Test.properties")

    最后,根据文档的指示,

    Foo.class.getResourceAsStream("Test.properties")将加载与类Foo位于同一个包中的Test.properties文件。

    Foo.class.getResourceAsStream("/com/foo/bar/Test.properties")将加载位于包com.foo.bar中的Test.properties文件。

    对于当getResourceAsStream()无法找到文件时的故障排除,getClass().getResource("").toURI())仍然很有用。注意使用""作为getResource方法的参数。

    解决方法是:确保要加载的文件位于类路径中,并使用getClass().getResourceAsStream()方法来获取InputStream。

    0