我有 jar 文件 langdetect.jar
。
它具有如图所示的层次结构
有一个类LanguageDetection
在com/langdetect
包裹。
我需要访问profiles.sm
的路径执行 jar 文件时从上面的类中获取的文件夹。
提前致谢。
最佳答案
Jars 只不过是 Zip 文件,Java 提供了处理这些文件的支持。
Java 6(及更早版本)
您可以将 jar 文件作为 ZipFile
打开并迭代它的条目。每个条目在文件内都有一个完整路径名,不存在相对路径名之类的东西。尽管您必须小心,所有条目(尽管在 zip 文件中是绝对的)都不要以“/”开头,如果您需要它,则必须添加它。以下代码片段将为您提供类文件的路径。 className
必须以 .class
结尾,即 LanguageDetection.class
String getPath(String jar, String className) throws IOException {
final ZipFile zf = new ZipFile(jar);
try {
for (ZipEntry ze : Collections.list(zf.entries())) {
final String path = ze.getName();
if (path.endsWith(className)) {
final StringBuilder buf = new StringBuilder(path);
buf.delete(path.lastIndexOf('/'), path.length()); //removes the name of the class to get the path only
if (!path.startsWith("/")) { //you may omit this part if leading / is not required
buf.insert(0, '/');
}
return buf.toString();
}
}
} finally {
zf.close();
}
return null;
}
Java 7/8
您可以使用 JAR 文件的 Java7 文件系统支持来打开 JAR 文件。这允许您像操作普通文件系统一样操作 jar 文件。因此,您可以遍历文件树,直到找到文件并从中获取路径。以下示例使用 Java8 Streams 和 Lambda,Java7 的版本可以从中派生,但会更大一些。
Path jarFile = ...;
Map<String, String> env = new HashMap<String, String>() {{
put("create", "false");
}};
try(FileSystem zipFs = newFileSystem(URI.create("jar:" + jarFileFile.toUri()), env)) {
Optional<Path> path = Files.walk(zipFs.getPath("/"))
.filter(p -> p.getFileName().toString().startsWith("LanguageDetection"))
.map(Path::getParent)
.findFirst();
path.ifPresent(System.out::println);
}
您的具体问题
上述解决方案用于查找 Jar 或 Zip 内的路径,但可能无法解决您的问题。
我不确定我是否正确理解你的问题。据我所知,您希望出于任何目的访问类文件夹内的路径。问题是,类/资源查找机制不适用于文件夹,仅适用于文件。接近的概念是包,但它总是绑定(bind)到类。
因此,您始终需要通过 getResource()
方法访问一个具体文件。例如MyClass.class.getResource(/path/to/resource.txt)
。
如果资源位于与类及其包相关的 profiles.sm
文件夹中,即在 /com/languagedetect/profile.sm/
中,您可以构建引用类的路径,例如该包中的类 LanguageDetection
并从中派生到 profile.sm 路径的绝对路径:
String basePath = "/" + LanguageDetection.class.getPackage().getName().replaceAll("\\.", "/") + "/profiles.sm/";
URL resource = LanguageDetection.class.getResource(basePath + "myResource.txt");
如果 jar 的根目录中只有一个 profiles.sm
,则只需转到
String basePath = "/profiles.sm/";
URL resource = LanguageDetection.class.getResource(basePath + "myResource.txt");
如果您有多个 jar 文件,其中的资源位于 /profiles.sm
中,您可以通过类加载器访问所有这些文件,然后从类的 URL 中提取 Jar 文件
for(URL u : Collections.list(LanguageDetection.class.getClassLoader().getResources("/profiles.sm/yourResource"))){
System.out.println(u);
}
无论如何,如果不访问 zip/jar 文件就不可能浏览此路径或文件夹的内容,因为 Java 不支持浏览类路径中的包/文件夹内的类或资源。您可以使用Reflections lib 为此,或者通过使用上面的 zip 示例另外读取检测到的 jar 的内容来扩展上面的 ClassLoader 示例。
关于java - jar 文件内的文件夹路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37113017/