通过getClass().getResource()加载文件
通过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文件和资源文件)...
- src
- SwingDemo
- CustomDialog.java
- Test.properties
- SwingDemo
当我在Eclipse中运行时,一切都运行正常。但是一旦我尝试从命令行运行应用程序,就会出现空指针异常。
命令行部署的层次结构如下:
文件夹:D:\Work\Java Progrms\SwingDemo
层次结构:
- SwingDemo
- CustomDialog.java
- Test.properties
首先,我在命令行中的SwingDemo
文件夹中编译了这个文件(javac CustomDialog.java
)。然后,我回到Java Programs文件夹(因为我在.java类中提到了包),并使用著名的命令运行应用程序
java SwingDemo.CustomDialog
以前,当我使用new FileInputStream("path")
时,我也遵循类似的步骤。
按照这种方式进行后,我得到了空指针异常。
我认为getClass().getResource(url)
无法从特定目录加载文件。这就是为什么我把资源文件放在与我的java文件相同的目录中。在Eclipse中它运行得很好。但是为什么在从命令行运行时会出错呢?
问题的出现原因是在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文件时,帮助我处理了一个文件的问题。
问题的原因是getClass().getResource()
方法使用类加载器来加载资源,这意味着资源必须在类路径下才能被加载。在使用Eclipse时,所有放在源文件夹中的内容都会被Eclipse编译:
在使用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。