以文件形式访问 Java 资源
Posted
技术标签:
【中文标题】以文件形式访问 Java 资源【英文标题】:Accessing a Java Resource as a File 【发布时间】:2012-05-23 05:29:24 【问题描述】:我正在尝试从类路径/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 转换为文件,但没有成功。
最坏情况的后备解决方案是将 InputStream 复制到文件系统上的一个文件,然后打开该文件,但我希望这不是必需的。
【问题讨论】:
Java Jar file: use resource errors: URI is not hierarchical 的可能重复项 @assylias:这个网站上有很多与这个问题相关的问题,但我找到的所有答案基本上都说“只使用 InputStream”。对我来说,这不是一个选择,这就是为什么我的问题是,除了我所说的 wort-case 方法之外,是否有任何方法可以将其作为文件访问。 【参考方案1】:简短的回答是你不能,因为资源不是文件。
如果第三方库想要做的只是从源读取数据(因此它应该采用InputStream
),或者第三方库实际上想要执行特定于文件的操作,那么它要么写得不好。
假设这不是库中可以修复的疏忽,您需要自己实际创建一个文件。尝试调用File.createTempFile()
,自己用资源的内容填充这个文件,然后将这个File
对象传递给库。 (当然,完成后删除它)。
【讨论】:
【参考方案2】:您不能以File
s 的身份直接访问这些已损坏的资源。相反,您需要将资源的内容复制到实际文件并将其传递给第 3 方库(您可以使用从 getResourceAsInputStream()
获得的 InputStream
)
【讨论】:
【参考方案3】:您可以编写一个由InputStream
、Byte Array
或ByteBuffer
支持的File
包装对象,然后将其传递到编写不佳的库代码中。
这并不简单,如果您不知道库在 File
对象上调用了哪些方法,则需要您编写每个方法的正确实现。
我在类似的情况下做过一次,但我知道调用的子集并且不必正确实现每个方法。您可能会很幸运,图书馆所做的唯一事情就是致电 .getInputStream()
并轻松完成。
【讨论】:
第 3 方库唯一要做的就是调用 FileInputStream 构造函数,并将 File 作为参数。您能否在 pastebin 上发布(重要部分)您的代码? 该代码在前任雇主处早已不复存在,但仅仅因为您所看到的只是FileInputStream
构造函数,并不意味着在 File
上没有其他调用需要。 FileInputStream
的源代码显示它比乍一看更复杂,因为也使用了FileDescriptor
。为InputStream
的特定实现硬编码的库比直接绑定到File
还要糟糕。编写此库的人需要审查他们的 OOD 技能。
FileInputStream 然后立即传递给 GZIPInputStream 构造函数。
他们应该只使用InputStream
而不是File
,你就会遇到这个问题。 GZIPInputStream
的来源仅向构造函数显示,两者都是 InputStream
,因此您可以使用我的解决方案仅公开 .getInputStream()
并让它工作。以上是关于以文件形式访问 Java 资源的主要内容,如果未能解决你的问题,请参考以下文章