java:获取正确的资源

java:获取正确的资源,java,resources,Java,Resources,我有一个库foo.jar,其中包含一个svversion.properties文件(看起来像svversion=12345M或其他什么),以及类svversion中的以下静态方法: public static SVNVersion fromString(String s) { ... } public static SVNVersion fromResources(Class<?> cl) { ResourceBundle svnversionResource = Resou

我有一个库
foo.jar
,其中包含一个
svversion.properties
文件(看起来像
svversion=12345M
或其他什么),以及
类svversion
中的以下静态方法:

public static SVNVersion fromString(String s) { ... }
public static SVNVersion fromResources(Class<?> cl) {
    ResourceBundle svnversionResource = ResourceBundle.getBundle(
        "svnversion", Locale.getDefault(), cl.getClassLoader());
    if (svnversionResource.containsKey("svnversion"))
    {
        String svnv = svnversionResource.getString("svnversion");
        return fromString(svnv);
    }
    else
    {
        return null;
    }
}
然后我打印结果,我看到
789
两次。显然,我做得不对。如何在包含给定类的jar文件的根目录中获得正确的
svversion.properties
文件?(假设它在那里)


编辑:我刚试过

InputStream is = cl.getResourceAsStream("/svnversion.properties");

它也有同样的问题。我似乎只能访问主jar文件的
/svversion.properties
,而不能访问库的
/svversion.properties

您显然不能使用这种方法,因为无论
svversion.properties
文件出现的是什么,都将始终使用类加载器。这与您在类中看到的行为相同:如果类路径上有两个同名的类,则使用的是最先出现的任何类

一种(复杂的)方法是找出类所属的jar,然后在该jar中检索
svversion.properties

public static JarFile getJarFile(Class<?> cl) {
    URL classUrl = cl.getResource(cl.getSimpleName() + ".class");
    if (classUrl != null) {
        try {
            URLConnection conn = classUrl.openConnection();
            if (conn instanceof JarURLConnection) {
                JarURLConnection connection = (JarURLConnection) conn;
                return connection.getJarFile();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    return null;
}

public static SVNVersion fromResources(Class<?> cl) {
    JarFile jarFile = getJarFile(cl);
    ZipEntry entry = jarFile.getEntry("svnversion.properties");
    Properties props = new Properties();
    try {
        props.load(jarFile.getInputStream(entry));
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

    if (props.containsKey("svnversion")) {
        String svnv = props.getProperty("svnversion");
        return fromString(svnv);
    } else {
        return null;
    }
}
publicstaticjarfile getJarFile(Class cl){
URL classUrl=cl.getResource(cl.getSimpleName()+“.class”);
if(classUrl!=null){
试一试{
URLConnection conn=classUrl.openConnection();
if(JarURLConnection的连接实例){
JarURLConnection连接=(JarURLConnection)conn;
返回连接。getJarFile();
}
}捕获(IOE异常){
抛出新的运行时异常(e);
}
}
返回null;
}
来自资源的公共静态SV转换(类别cl){
JarFile JarFile=getJarFile(cl);
ZipEntry entry=jarFile.getEntry(“svversion.properties”);
Properties props=新属性();
试一试{
load(jarFile.getInputStream(entry));
}捕获(IOE异常){
抛出新的运行时异常(e);
}
if(道具容器(“转换”)){
字符串svnv=props.getProperty(“svnversion”);
从字符串返回(svnv);
}否则{
返回null;
}
}

这就是为什么,IMHO,您最好将svn版本号作为最终静态变量存储在类中(并使用svn
$Revision$
关键字)。

给出不同的类名并不一定意味着不同的类加载器。我认为这样做是不可能的this@Teja:我想出来了。:-)我对如何正确操作很感兴趣。您能解释一下如何操作吗?svn关键字替换的可能重复项,例如$Revision$仅适用于单个文件;我想要在整个签出中运行svnversion.exe的结果。无论如何,问题不只是svn版本,而是从库JAR和应用JAR中获取资源。谢谢你的其他建议。我确实明白了,但很明显你误解了类加载的工作方式。除非你在不同的类装入器中装入不同的JAR,否则你永远无法实现你想要的。“但很明显,你误解了类装入的工作方式。”——我一点也没有误解类装入。我所误解的是getResource()和getResourceStream()以及getResourceBundle()与类加载器协同工作的方式。
public static JarFile getJarFile(Class<?> cl) {
    URL classUrl = cl.getResource(cl.getSimpleName() + ".class");
    if (classUrl != null) {
        try {
            URLConnection conn = classUrl.openConnection();
            if (conn instanceof JarURLConnection) {
                JarURLConnection connection = (JarURLConnection) conn;
                return connection.getJarFile();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    return null;
}

public static SVNVersion fromResources(Class<?> cl) {
    JarFile jarFile = getJarFile(cl);
    ZipEntry entry = jarFile.getEntry("svnversion.properties");
    Properties props = new Properties();
    try {
        props.load(jarFile.getInputStream(entry));
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

    if (props.containsKey("svnversion")) {
        String svnv = props.getProperty("svnversion");
        return fromString(svnv);
    } else {
        return null;
    }
}