【问题标题】:can't add current directory to classpath [duplicate]无法将当前目录添加到类路径 [重复]
【发布时间】:2014-08-16 03:46:49
【问题描述】:

当前状态 正如克里斯建议的那样,我创建了一个最小示例(基于 maven):

public class MainApp {
    public static void main(String[] args) {
        System.out.println(MainApp.class.getResourceAsStream("/my.properties"));
        System.out.println(MainApp.class.getClassLoader().getResourceAsStream("their.properties"));
    }
}

这是有效的(与我不工作的应用程序中相同的 Maven 配置,以及相同位置的相同 MANIFEST.MF)! 所以我只是将上面的 2 行复制到我的真实应用程序中,构建它并将 2 个文件复制到 jar 的文件夹中。但现在两个系统输出都产生“null”! 所以似乎有些东西在摆弄类路径/或者让从清单中忽略类路径? (打印出类路径的输出在两种情况下都是相同的 - 仅打印出 jar) 知道如何解决这个问题吗?

原始问题:

我在从当前目录读取文件(属性)时遇到问题。这是我的设置(基于 Maven): 文件读取:

MyClass.class.getClassLoader().getResourceAsStream("my.properties")

在我的属性放置在 resources/my.properties 中的测试中工作正常。

由于当前目录是默认的类路径,我认为将 my.properties 放在与 jar 相同的目录中并从该目录运行 java -jar 应该可以,但它不起作用(资源流为空)。 然后我在 main 中添加了奇怪的代码以打印出类路径:

String classpath = System.getProperty("java.class.path");
String[] classpathEntries = classpath.split(File.pathSeparator);
for (int i = 0; i < classpathEntries.length; i++) {
    System.out.println(classpathEntries[i]);
}

我还尝试了一些其他代码,但在这两种情况下,都只打印了我的 jar 文件的路径。所以我尝试添加“。”使用 maven 程序集插件来清单。来自清单:

...
Class-Path: .
...

但这并没有帮助。那么如何让我的程序从当前目录加载getClassLoader().getResourceAsStream(my.properties)呢?

为什么这不是this的重复项 我从类路径加载资源没有问题。我把文件放在 src/test/resource/my.properties Maven 将它们与所有类一起复制,一切正常。由于该文件位于 src/test/resources 中,因此打包的 jar 中缺少它(如预期的那样)。用户必须提供一个 my.properties 才能运行该程序。我想从当前目录中读取这个文件(假设 java - jar 是从带有 jar 和 my.properties 的目录中调用的)但这不起作用!

编辑 maven-assembly-plugin 配置:

        <configuration>
            <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
            <archive>
                <manifest>
                    <mainClass>some.pkg.MainApp</mainClass>
                </manifest>
                <manifestEntries>
                    <Class-Path>.</Class-Path>
                </manifestEntries>
            </archive>
        </configuration>

这会导致清单 ...jar/META-INF/MANIFEST.MF

【问题讨论】:

  • 你需要String in getResourceAsStream("my.properties")
  • 添加资源的“maven”方式是将其添加到/src/main/resources。然后 Maven 将放置在正确的位置,以便 getClassLoader().getResourceAsStream("/my.properties") 以您期望的方式工作
  • 我的问题是它采用了 maven 方式,在测试中一切正常,因为 my.properties 位于正确的位置(src/test/resources)。但是如果将文件放在当前目录中,则在运行时找不到该文件(用户强制交付一个,未提供默认值)

标签: java classpath


【解决方案1】:

在 Ubuntu 上运行 Java 1.7.0_51-b13 (Oracle),您的方法对我来说效果很好。因此,要么版本引入了差异,要么运行测试的方式出现了微妙的变化。以下是我进行测试的方法,也许它可以帮助您进一步诊断。

这是我使用的清单

Manifest-Version: 1.0
Class-Path: .
Main-Class: Foo
Created-By: 1.7.0_06 (Oracle Corporation)

还有代码

public class Foo {

    public static void main( String[] args ) {
      Object v = Foo.class.getClassLoader().getResourceAsStream("my.properties");

      System.out.println( "v = " + v );
    }
}

我按如下方式创建了 jar:

jar cfm MyJar.jar Manifest.txt Foo.class

然后我将 jar 移到它自己的目录中并运行

cd dirContainingJar
java -jar MyJar.jar

它打印了null,所以我然后

echo Hello > my.properties
java -jar MyJar.jar

它打印出来了

v = java.io.BufferedInputStream@131b92e6

【讨论】:

  • 我正在使用 maven - 我将尝试使用 maven 创建一个最小示例...让我们看看
  • 是否使用 Maven 无关紧要,只要创建的 jar 文件正确即可。值得打开该 jar 文件并用肉眼检查它。特别是 MANIFEST.MF 文件;可能没有为您正确获取。确保您使用的是 Maven 清单标签,而不仅仅是包含资源下的文件。
  • 我更新了我的问题,但我认为 manifest 一切都很好,因为调用 main 工作正常(在那里指定了主类)
  • 我使用您在上面提供的规范敲了一个 pom.xml,并且还生成了一个为我运行的 jar 文件。这听起来越来越成为版本/环境。
  • 稍微搁置最初的问题,并考虑实现最终目标的替代方法。您是否考虑过使用 Properties.load 代替?这不太可能如此古怪。然后您可以使用系统属性 user.dir 来获取用户当前目录。
猜你喜欢
  • 1970-01-01
  • 2018-04-14
  • 1970-01-01
  • 2020-06-02
  • 1970-01-01
  • 2016-06-03
  • 1970-01-01
  • 2014-09-29
  • 1970-01-01
相关资源
最近更新 更多