4

这个话题有很多混乱。已经提出了几个问题。事情似乎还不清楚。ClassLoader、绝对文件路径等

假设我有一个项目目录结构,

我的项目 - 
            --dist        
            --lib
            --src
            - 测试

我在“lib/txt”目录中有一个资源说“txtfile.txt”。我想以独立于系统的方式访问它。我需要项目的绝对路径。所以我可以将路径编码为 abspath+"/lib/Dictionary/txtfile.txt"

假设我这样做

 java.io.File file = new java.io.File("");   //Dummy file
    String  abspath=file.getAbsolutePath();

我得到了不一定是项目根目录的当前工作目录。

假设我从“dist”文件夹中执行最终的“prj.jar”,该文件夹还包含“lib/txt/txtfile.txt”目录结构和资源,它也应该在这里工作。我应该是 dist 文件夹的绝对路径。

希望问题很清楚。

4

3 回答 3

9

你真的应该使用你的类加载器来使用getResource()getResourceAsStream()来处理这类事情。特别是,这些方法使用您的 ClassLoader 来确定项目中资源的搜索上下文。

指定类似getClass().getResource("lib/txtfile.txt")的内容以获取文本文件。

澄清一下:与其考虑如何获取资源的路径,不如考虑获取资源——在这种情况下,是某个目录中的文件(可能在您的 JAR 中)。在这种情况下,不需要知道一些绝对路径,只需要一些 URL 来获取文件,ClassLoader 会为您返回这个 URL。如果您想打开文件的流,您可以直接执行此操作,而无需使用getResourceAsStream.

您尝试通过 ClassLoader 访问的资源需要位于 Class-Path 上(在 JAR 文件的 Manifest 中配置)。这很关键!ClassLoader 使用 Class-Path 来查找资源,因此如果您没有在 Class-Path 中提供足够的上下文,它将无法找到任何东西。如果您添加.ClassLoader,则应该根据您引用资源的方式来解析 JAR 内部或外部的任何内容,尽管您当然可以更具体。

引用前缀为 a 的资源.将导致 ClassLoader 也查找 JAR 之外的文件,而不使用句点作为前缀的资源路径将指示 ClassLoader 仅查找 JAR 文件内部。

这意味着如果您在 JAR 中的某个目录中有一些文件并且libfoo.txt想要获取该资源,那么您将运行getResource("lib/foo.txt");

如果相同的资源在你运行的 JAR 之外getResource("./lib/foo.txt");

于 2010-07-09T04:50:13.100 回答
2

首先,确保 lib 目录在您的类路径中。您可以通过在启动脚本中添加命令行参数来做到这一点:

$JAVA_HOME/bin/java -classpath .:lib com.example.MyMainClass

将此保存为 MyProject/start.sh 或任何依赖于操作系统的脚本。

然后你可以访问 textfile.txt (正如马克正确提到的):

// if you want this as a File
URL res = getClass().getClassLoader().getResource("text/textfile.txt");
File f = new File(res.getFile());

// As InputStream
InputStream in = getClass().getClassLoader()
        .getResourceAsStream("text/textfile.txt");
于 2010-07-09T05:09:54.503 回答
0

@Mark 是正确的。这是迄今为止最简单、最稳健的方法。

但是,如果您真的必须拥有一个File,那么您最好的选择是尝试以下方法:

  • 将系统属性“java.class.path”的内容转换为路径名列表,
  • 根据文件名识别列表中的 JAR 路径名,
  • 找出“../..”相对于 JAR 路径名的内容,从而为您提供“项目”目录,以及
  • 构建相对于项目目录的目标路径。

另一种选择是将项目目录名称嵌入到包装脚本中,并使用 -D 选项将其设置为系统属性。也可以让包装脚本找出它自己的绝对路径名;例如使用whence.

于 2010-07-09T04:55:29.407 回答