作为文件访问Java资源

6

我正在尝试将类路径/JAR文件中的资源作为File对象访问。我知道使用InputStream对象是首选方法,但我正在使用一个需要File对象的外部库(WorldEdit)。

以下是我的代码:

InputStream templStream = "".getClass().getResourceAsStream("/res/template.prom");
System.out.println("templateStream: " + templStream.toString());
File templFile = new File("".getClass().getResource("/res/template.prom").toURI());
System.out.println("templateFile: " + templFile.canRead());

现在,当我仍然在eclipse中时,访问资源的两种方式都可以完美地工作,并产生以下输出:
templStream: java.io.BufferedInputStream@746d1683
templFile: true

但是当将代码导出为JAR档案后,代码会失败:
templStream: sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream@47aa261b
Exception in thread "main" java.lang.IllegalArgumentException: URI is not hierarchical
    at java.io.File.<init>(File.java:392)
    at SMCToPROM.main(SMCToPROM.java:101)

我一直在寻找一种方法,直接访问资源作为文件,或者使用InputStream并将其转换为文件,但是一直没有成功。

最坏的情况下,备选方案是将InputStream复制到文件系统中的文件,然后打开该文件,但希望不必这样做。


@assylias:这个问题在这个网站上有很多相关的问题,但我找到的所有答案基本上都是“只需使用InputStream即可”。对我来说,这不是一个选项,这就是为什么我的问题是是否有任何方法(除了我已经提到的最坏情况),可以将其作为文件访问。 - mic_e
3个回答

5
简短的回答是您不能这样做,因为该资源不是一个文件。
如果第三方库只是想从源中读取数据(因此应使用InputStream),则该库编写得很差。
或者该库实际上需要进行特定于文件的操作。 假设这不是可以修复的库中的疏忽,那么您需要自己创建一个文件。尝试调用File.createTempFile(),自己填充此文件的内容,然后将此File对象传递给库。(当然完成后要删除它)。

3

直接访问被打包成jar的资源作为File是不允许的。相反,您需要将资源的内容复制到实际文件中,并将其传递给第三方库(可以使用getResourceAsInputStream()返回的InputStream来完成这一点)。


1
你可以编写一个File包装对象,它由InputStreamByte ArrayByteBuffer支持,然后将其传递给编写不良的库代码。
这并不简单,如果你不知道该库在File对象上调用哪些方法,就需要编写每个方法的正确实现。
我曾经在类似的情况下做过这件事,但我知道子集调用,并不需要正确实现每个方法。你可能会很幸运,库只是调用.getInputStream(),这样就容易解决了。

第三方库所做的唯一事情就是使用文件作为参数调用FileInputStream构造函数。您能否在pastebin上发布(代码的重要部分)? - mic_e
那段代码早已经在以前的雇主那里消失了,但仅仅因为你只能看到FileInputStream构造函数,并不意味着File上没有其他不必要的调用。FileInputStream的源代码显示它比第一眼看起来更复杂,因为还使用了FileDescriptor。将库硬编码为特定的InputStream实现甚至比直接绑定到File更糟糕。写这个库的人需要重新审查他们的面向对象设计技巧。 - user177800
FileInputStream 立即传递给 GZIPInputStream 构造函数。 - mic_e
他们应该只是使用 InputStream 而不是 File,这样你就不会遇到这个问题了。GZIPInputStream 的源代码只显示了两个构造函数,都是 InputStream,所以你可以使用我的解决方案来仅暴露 .getInputStream() 并使其正常工作。 - user177800

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接