jar 文件内的文件夹路径

Rav*_*att 3 java jar

我有 jar 文件langdetect.jar。它具有如图所示的层次结构

显示jar内的项目结构

LanguageDetection包里有一个课程com/langdetect。我需要profiles.sm在执行 jar 文件时从上面的类访问文件夹的路径。

提前致谢。

Ger*_*cke 5

Jars 只不过是 Zip 文件,Java 提供了处理这些文件的支持。

Java 6(及更早版本)

您可以将 jar 文件打开为 aZipFile并迭代它的条目。每个条目在文件内都有一个完整路径名,不存在相对路径名之类的东西。尽管您必须小心,所有条目(尽管在 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;
}
Run Code Online (Sandbox Code Playgroud)

爪哇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);
}
Run Code Online (Sandbox Code Playgroud)

你的特殊问题

上述解决方案用于查找 Jar 或 Zip 内的路径,但可能无法解决您的问题。

我不确定我是否正确理解你的问题。据我所知,您希望出于任何目的访问类文件夹内的路径。问题是,类/资源查找机制不适用于文件夹,仅适用于文件。接近的概念是包,但它总是绑定到类。

所以你总是需要一个通过方法访问的具体文件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");
Run Code Online (Sandbox Code Playgroud)

profiles.sm如果罐子的根目录中只有一个,则只需执行

String basePath = "/profiles.sm/";
URL resource = LanguageDetection.class.getResource(basePath + "myResource.txt");
Run Code Online (Sandbox Code Playgroud)

如果您有多个包含资源的 jar 文件/profiles.sm,您可以通过类加载器访问所有这些文件,然后从类的 URL 中提取 Jar 文件

for(URL u : Collections.list(LanguageDetection.class.getClassLoader().getResources("/profiles.sm/yourResource"))){
        System.out.println(u);
    }
Run Code Online (Sandbox Code Playgroud)

无论如何,如果不访问 zip/jar 文件就不可能浏览此路径或文件夹的内容,因为 Java 不支持浏览类路径中的包/文件夹内的类或资源。您可以使用Reflections lib 来实现此目的,或者通过使用上面的 zip 示例额外读取检测到的 jar 的内容来扩展上面的 ClassLoader 示例。