Java 打开文件;首先尝试文件系统,然后尝试JARs

Java 打开文件;首先尝试文件系统,然后尝试JARs,java,jar,classpath,classloader,Java,Jar,Classpath,Classloader,我试图让我的应用程序透明地加载资源(二进制文件): 如果文件存在于当前目录下,请将其打开。 如果没有,请尝试查找当前JAR文件(如果适用)。 如果没有,请尝试查找其他JAR文件。(这是可选的,我不介意显式指定哪些JAR文件。) 到目前为止,我知道File可以打开一个本地文件,而ClassLoader可以为JAR内容提供getResource* 有一个结合了这两者的类吗?如果没有,我该如何着手自己写呢?我应该写一个ClassLoader,它也检查本地文件系统吗?使用文件?(我对Java非常不熟悉,

我试图让我的应用程序透明地加载资源(二进制文件):

如果文件存在于当前目录下,请将其打开。
如果没有,请尝试查找当前JAR文件(如果适用)。
如果没有,请尝试查找其他JAR文件。(这是可选的,我不介意显式指定哪些JAR文件。)

到目前为止,我知道
File
可以打开一个本地文件,而
ClassLoader
可以为JAR内容提供
getResource*

有一个结合了这两者的类吗?如果没有,我该如何着手自己写呢?我应该写一个
ClassLoader
,它也检查本地文件系统吗?使用
文件
?(我对Java非常不熟悉,甚至不知道返回哪种类型比较好。
InputStream
?)

谢谢

另外,我说的“文件”是指“路径”,例如“data/texture1.png”。

如果文件路径位于jar前面的类路径上,A应该能够同时加载这两个文件并首先尝试文件路径


关于你的评论:

  • 我知道相对的jar URL不会 工作这就是为什么春天来了 完成资源抽象。
  • 你可能想检查一下答案 关于这个问题:。问题类似于 你的
做1和3很容易。做#2(只看当前的罐子)要困难得多,因为它需要你弄清楚你想要什么罐子

如果您想先检查文件系统,否则从类路径加载,它将类似于:

public java.io.InputStream loadByName(String name) {
  java.io.File f = new java.io.File(name);
  if (f.isFile()) {
    return new FileInputStream(f);
  } else {
    return getClass().getResource(name);
  }
}

如果您希望首先从同一个JAR文件加载,那么需要弄清楚它在哪里。查看了解有关确定要从中加载资源的JAR文件的更多信息。

当前JAR文件和当前目录在JVM中并不像在运行shell脚本时那样是概念。您需要指定一个目录,用于加载感兴趣的文件,例如在执行JVM时使用系统属性:

java -Ddirectory.to.scan=/home/aib
然后检索此属性:

String dir = System.getProperty("directory.to.scan");
现在在讨论JAR文件时,启动JVM时在类路径上显式指定的所有JAR文件都由类加载器加载。您可以通过以下方式获取特定类的类加载器:

InputStream is = <Your class>.class.getClassLoader().getResourceAsStream("binary file");
InputStream是=.class.getClassLoader().getResourceAsStream(“二进制文件”);

请注意,当前类加载器加载的任何jar文件都会被搜索。

Ah,太好了。这可能正是我要找的。事实上确实如此!但有一个问题:为什么我不能使用
新的URL(“file:foo.jar!/data”)
?我似乎不能使用
/完全正确!还有一件事,它似乎更喜欢JAR中的文件,不管我给路径的顺序是什么。谢谢你的指针。我可以解决JAR相对路径的问题,但是首先扫描JAR呢?除非删除JAR中的文件,否则无法访问文件系统中的文件。似乎URL搜索顺序是始终首先搜索JAR,而不管它是我传递给构造函数的URL数组的第一个还是第二个元素。我想说的是跳过显式类加载器调用,只需配置JAR清单,如另一个问题中所述。我担心我可能需要这样的函数:(-谢谢你指出另一个问题,顺便说一句。