【问题标题】:Accessing a Java Resource as a File以文件形式访问 Java 资源
【发布时间】: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 复制到文件系统上的一个文件,然后打开该文件,但我希望这不是必需的。

【问题讨论】:

  • @assylias:这个网站上有很多与这个问题相关的问题,但我找到的所有答案基本上都说“只使用 InputStream”。对我来说,这不是一个选择,这就是为什么我的问题是,除了我所说的 wort-case 方法之外,是否有任何方法可以将其作为文件访问。

标签: java file resources inputstream


【解决方案1】:

简短的回答是你不能,因为资源不是文件。

如果第三方库想要做的只是从源读取数据(因此它应该采用InputStream),或者第三方库实际上想要执行特定于文件的操作,那么它要么写得不好。

假设这不是库中可以修复的疏忽,您需要自己实际创建一个文件。尝试调用File.createTempFile(),自己用资源的内容填充这个文件,然后将这个File 对象传递给库。 (当然,完成后删除它)。

【讨论】:

    【解决方案2】:

    您不能以Files 的身份直接访问这些已损坏的资源。相反,您需要将资源的内容复制到实际文件并将其传递给第 3 方库(您可以使用从 getResourceAsInputStream() 获得的 InputStream

    【讨论】:

      【解决方案3】:

      您可以编写一个由InputStreamByte ArrayByteBuffer 支持的File 包装对象,然后将其传递到编写不佳的库代码中。

      这并不简单,如果您不知道库在 File 对象上调用了哪些方法,则需要您编写每个方法的正确实现。

      我在类似的情况下做过一次,但我知道调用的子集并且不必正确实现每个方法。您可能会很幸运,图书馆所做的唯一事情就是致电 .getInputStream() 并轻松完成。

      【讨论】:

      • 第 3 方库唯一要做的就是调用 FileInputStream 构造函数,并将 File 作为参数。您能否在 pastebin 上发布(重要部分)您的代码?
      • 该代码在前任雇主处早已不复存在,但仅仅因为您所看到的只是 FileInputStream 构造函数,并不意味着在 File 上没有其他调用需要。 FileInputStream 的源代码显示它比乍一看更复杂,因为也使用了FileDescriptor。为InputStream 的特定实现硬编码的库比直接绑定到File 还要糟糕。编写此库的人需要审查他们的 OOD 技能。
      • FileInputStream 然后立即传递给 GZIPInputStream 构造函数。
      • 他们应该只使用InputStream 而不是File,你就会遇到这个问题。 GZIPInputStream 的来源仅向构造函数显示,两者都是 InputStream,因此您可以使用我的解决方案仅公开 .getInputStream() 并让它工作。
      猜你喜欢
      • 2013-12-29
      • 1970-01-01
      • 1970-01-01
      • 2013-07-18
      • 2011-11-05
      • 2021-03-24
      • 1970-01-01
      • 2012-08-16
      • 2011-07-08
      相关资源
      最近更新 更多