我之前遇到过这个问题好几次。
我希望在JDK 7中有人能编写一个classpath文件系统,但可惜并没有。
Spring有Resource类,可以很好地加载classpath资源。
答案非常好,但我认为我可以通过展示一个适用于作为classpath资源的文件和目录的示例来增加讨论。
我写了一个小型原型来解决这个问题。该原型不能处理每个边缘情况,但它确实可以处理在jar文件中的目录中查找资源的情况。
我已经使用Stack Overflow相当长时间了。如果我回答得太长,请原谅(这是我的天性)。
/**
* 原型资源读取器。
* 此原型不包含错误检查。
*
*
* 我有两个设置好的原型jar文件。
*
* <dependency>
* <groupId>invoke</groupId>
* <artifactId>invoke</artifactId>
* <version>1.0-SNAPSHOT</version>
* </dependency>
*
* <dependency>
* <groupId>node</groupId>
* <artifactId>node</artifactId>
* <version>1.0-SNAPSHOT</version>
* </dependency>
*
* 这些jar文件下各有一个名为resource.txt的文件,位于/org/node/目录下。
*
* 这只是一个类似于classpath://处理程序的原型。
* 我还在本项目的本地资源中添加了一个resource.foo.txt文件。
*
*/
public class ClasspathReader {
public static void main(String[] args) throws Exception {
/* 此项目包括两个jar文件,每个文件都有一个位于/org/node/目录下的资源,名为resource.txt。*/
/*
命名空间只是我用来查看目录中文件是否以命名空间开头的设备。
将命名空间视为文件扩展名,但它是文件的开始而不是结尾。
*/
String namespace = "resource";
//someResource是classpath。
String someResource = args.length > 0 ? args[0] :
//"classpath:///org/node/resource.txt"; It works with files
"classpath:///org/node/"; //It also works with directories
URI someResourceURI = URI.create(someResource);
System.out.println("资源的URI = " + someResourceURI);
someResource = someResourceURI.getPath();
System.out.println("资源的路径 =" + someResource);
boolean isDir = !someResource.endsWith(".txt");
/** Classpath资源实际上永远不会以斜杠开头。
* 逻辑上它们确实是,但实际上你必须剥离它。
* 这是classpath资源的已知行为。
* 它使用斜杠工作,除非资源在jar文件中。
* 底线是,通过剥离它,它总是有效的。
*/
if (someResource.startsWith("/")) {
someResource = someResource.substring(1);
}
/* 使用ClassLoader查找所有具有此名称的资源。
查找与我们正在查找的位置匹配的所有资源。*/
Enumeration resources = null;
/* 首先检查上下文类加载器。如果可以使用,请始终使用它。*/
try {
resources =
Thread.currentThread().getContextClassLoader().getResources(someResource);
} catch (Exception ex) {
ex.printStackTrace();
}
if (resources == null || !resources.hasMoreElements()) {
resources = ClasspathReader.class.getClassLoader().getResources(someResource);
}
//现在遍历来自类路径的资源的URL
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
/* 如果资源是文件,则只是意味着我们可以使用正常机制来扫描目录。*/
if (resource.getProtocol().equals("file")) {
//如果它是一个文件,那么我们可以用正常的方式处理它。
handleFile(resource, namespace);
continue;
}
System.out.println("资源 " + resource);
/*
将这个字符串拆分成这样:
jar:file:/Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar!/org/node/
分成
这个 /Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar
和这个
/org/node/
*/
String[] split = resource.toString().split(":");
String[] split2 = split[2].split("!");
String zip
您可以在此处查看一个完整的示例及其输出。