classloader.getresourceasstream如何工作?

ztyzrc3y  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(437)

我用maven创建了一个jar文件。当我打开这个jar时,我可以找到以下内容:

my.jar
|_text1.txt
|_folder
|_ ... some other stuff

当我在eclipse中运行这个代码段时,“text1.txt”的内容和打印出来的文件夹内容中的所有文件名

String tmp = IOUtils.toString(App.class.getClassLoader().getResourceAsStream("text1.txt"), StandardCharsets.UTF_8);
System.err.println(tmp);

tmp = IOUtils.toString(App.class.getClassLoader().getResourceAsStream("folder"), StandardCharsets.UTF_8);
System.err.println(tmp);

当我将此代码作为独立程序运行时,也会打印“text1.txt”中的内容,但文件夹的第二部分返回null。
我做错什么了?

5anewei6

5anewei61#

App.class.getClassLoader().getResourceAsStream 别这样。正确的方法是 App.class.getResourceAsStream . 有时候 getCLassLoader() 返回null;在这种情况下,你的策略被打破了,上面的就可以了。另外,你的方式是更多的调用和更多的代码没有收益。 IOUtils.toString(App.class.getClassLoader().getResourceAsStream("folder") 无法获取“文件夹”。你觉得这样会怎么样?设计到资源加载器系统中的抽象(这是您在这里使用的)不允许您以任何方式获取文件夹,也不允许您列出文件夹的内容(您可能正在寻找spi:服务提供者接口(serviceproviderinterface)。 IOUtils 你不需要这个; java.nio.file.Files 是内置的,并且具有相同的tostring方法。它甚至默认为 UTF-8 所以你不必指定它。 App.class.getResourceAsStream("text1.txt") 这将在与app.class完全相同的位置查找t1.txt。即使是相同的包结构。如果您想从app.class所在的“根”开始查找(那么 -classpath ,一般情况下),在前面加一个斜杠:ask for "/text1.txt" 例如)。
假设您在根目录中有text1.txt,而不是在 com/foo/pkg 旁边 com/foo/pkg/MyApp.class ,您需要指定 "/text1.txt" 找到它。
如果您不确定这些东西在哪里,请查看此调用的结果:

App.class.getResource("App.class");

这将打印一个网址,从中你的眼球将能够告诉它在哪里寻找。
以及打印出来的文件夹内容中的所有文件名
那很好。这是行不通的——eclipse在运行时给您提供了这一点是很奇怪的,但是规范基本上对此没有抽象。classloader实现可以做任何他们想做的事情(这是一个可插拔的系统),他们需要实现的唯一方法是“在这个位置找到资源”。如果您要求一个“文件夹”,则没有义务返回一个文件名字符串,而大多数类加载器(包括读取jar文件的类加载器)根本没有义务。
解决方案是spi:在编译时生成一个列出路径或类名的文件,然后在运行时使用资源系统加载该文件,然后加载其中列出的每个类/每个资源。注解处理器可以自动生成这个文件,作为编译的一部分,使整个过程无缝衔接。有关更多信息,请在web上搜索spi java。

相关问题