【问题标题】:Equivalent of this.getClass().getClassLoader().getResource(".").toURI() from within a Jar相当于 Jar 中的 this.getClass().getClassLoader().getResource(".").toURI()
【发布时间】:2015-04-13 18:14:02
【问题描述】:

我正在尝试实现一种在从 jar 中运行时获取当前类加载器的基本路径的方法。

我的意思是编程,我已经知道它应该是“jarPath+jarFile.jar!/”的形状

与文件系统的调用不同,getResource(".") 或 .getResource("/") 在 jar 中不起作用。

理想情况下,它应该是任何文件提供者的抽象解决方案,例如:

Path BASE_PATH = Paths.get(...getResource("").toURI())

它可以为 jars 和文件系统返回正确的根路径,这样我就可以使用我的资源的相对 url,而无需执行任何条件语句和 url 手动字符串解析/构建。

【问题讨论】:

  • jar 中没有“根路径”这样的东西,因为它不是文件系统的一部分。你到底想做什么?
  • 如果你在寻找资源的相对路径,SomeClass.class.getResource("foo.jpg") 有什么问题,它从与SomeClass 相同的包中加载 foo.jpg 文件?你想解决什么具体问题?
  • 读取不是问题,因为我在路径中指定了资源,但我也需要列出/写入基本目录,我不想做 getResource("com") .getPaarent() 气味最终容易出错
  • @user1352530 存储在 jar 文件中的资源没有“目录”。如果资源保存在 jar 中,那么您需要获取 jar 所在的目录并将其用作您的信息,而不是完全依赖 getResource() 返回的内容。
  • 在通过路径和文件 NIO 类读取文件夹 input/resource.txt 时,我可以在两种情况下使用相同的代码(jar/fs)

标签: java maven jar resources classloader


【解决方案1】:

您应该能够使用以下代码找出包含您的类或任何资源的 jar 和/或目标文件夹的路径:

package com.stackoverflow.test;

import java.net.URL;
import java.nio.file.Paths;

public class ClassPathUtils {

  public static String getBasePath(String jarPath) {
    String path = getJarPathFromClass(jarPath);
    if (path == null) {
      return null;
    }

    if (path.startsWith("jar:")) {
      path = path.substring("jar:".length());
    }
    if (path.startsWith("file:")) {
      path = path.substring("file:".length());
    }
    if (path.endsWith(jarPath)) {
      path = path.substring(0, path.length()-jarPath.length());
    }

    return path;
  }
  public static String getBasePath(Class clazz) {
    return getBasePath(classNameDotClass(clazz));
  }
  private static String classNameDotClass(Class clazz) {
    return clazz.getName().replaceAll("\\.", "/") + ".class";
  }
  private static String getJarPathFromClass(String resource) {
    final URL url = ClassPathUtils.class.getClassLoader().getResource(resource);
    return url == null ? null : url.toString();
  }
  public static void main(String[] args) {
    //System.out.println(Paths.get(ClassPathUtils.getBasePath("."))); // doesn't work in a jar
    System.out.println(Paths.get(ClassPathUtils.getBasePath(ClassPathUtils.class)));

    System.out.println(Paths.get(ClassPathUtils.getBasePath("fonts/atcitadelscript.ttf"))); // any classpath resource

    System.out.println(Paths.get(ClassPathUtils.getBasePath(String.class))); // actually finds rt.jar

  }
}

如果您从 IDE 或 maven 运行此代码,它将为您提供自己的资源的目标/类路径,或其他资源的 jar 路径(例如 String.class)。 如果你从 jar 中调用它,它总是会告诉你 jar 文件的路径。

从 IDE 运行:

/home/alexander/projects/stackoverflow/stuff/target/classes
/home/alexander/projects/stackoverflow/stuff/target/classes
/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar!`

从 JAR 运行:

/home/alexander/projects/stackoverflow/stuff/target/test-stuff-0.1-SNAPSHOT.jar!
/home/alexander/projects/stackoverflow/stuff/target/test-stuff-0.1-SNAPSHOT.jar!
/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar!

这就是你要找的吗?

【讨论】:

  • 谢谢,但我正在寻找一种获取类加载器基本路径的方法,当案例从 jar 运行并事先知道具体资源时,无需手动构建。
  • “类加载器基本路径”和“具体资源”是什么意思?您不能始终从任何调用类提供 getClass() - 每个类都应该为您提供包含该类的 jar。你能提供更多信息吗?一个例子?
  • 我有一个相对 URL,例如“myXTypeResources/resource.csv”。我只是在 Jar 或 src/main/resources=target/classes 中获取根文件夹的 Path 变量,所以我真的不介意从 jar 或文件系统运行代码。如果 ”。”或 "/" 在 jar 上工作,就像 Path basePath = Paths.get(...getClassLoader.getResource(".").toUri()) 一样简单
猜你喜欢
  • 2011-04-17
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
相关资源
最近更新 更多