【问题标题】:Absolute Path of Project's folder in JavaJava中项目文件夹的绝对路径
【发布时间】:2011-03-13 16:48:23
【问题描述】:

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

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

我的项目 - --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 文件夹的绝对路径。

希望问题很清楚。

【问题讨论】:

  • 此外,我觉得这种方法仍然仅限于“Unix”之类的目录结构平台,因为在 Windows 上附加“/lib/Dictionary/txtfile.txt”会因为正斜杠和反斜杠的不同而搞砸! :|
  • 实际上,Java 并不关心斜线方向,尽管您只能显式指定非根驱动器,因为/ 指向当前磁盘的根目录。
  • System.getProperty("file.separator") 将为 Windows 环境返回“\”,为 Unix(和类 Unix)环境返回“/”。
  • @Catchwa,是的,文件分隔符,但是 Java 仍然会使用正斜杠识别路径,下次在 Windows 上需要路径时尝试使用它们。跨度>
  • 解决方案有三种变体,视情况而定:stackoverflow.com/a/56327069/715269

标签: java deployment absolute-path


【解决方案1】:

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

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

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

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

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

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

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

【讨论】:

  • 正如我所提到的,我已经尝试过使用类加载器。您能否发布一些关于在我的情况下如何处理它的 sn-p?
  • @MArk 我理解它必须由类加载器处理的事实。但如何? java.net.URL url =getClass().getResource("lib/txtfile.txt");为我返回一个空 URL!
  • @Mark dist 文件夹有一个 prj.jar + 一个“lib/txt/txtfile”资源。 (资源在 jar 外发送)我打算最后将 dist 文件夹 tar 以分发它
  • @Myth17,在这种情况下您需要添加“。”到 JAR 清单中的类路径,调用应该是 getResource("lib/txt/txtfile")
  • @MArk 我添加了这个 java.net.URL url=getClass().getClassLoader().getResource("english.txt"); java.net.URL url2 =getClass().getClassLoader().getResource("common-misspells.txt"); lib/Dictionary 已经在我的类路径中了。 sc.initialize(url.getPath(),url2.getPath());其中 initialize 是我必须使用的库方法。这在我从 netbeans 编译时有效,但 dist 文件夹中的 jar 文件仍然无法找到字典文件(尽管它们也存在于那里)。甚至 MANIFEST.MF 也包括: Class-Path: lib/jaspellbin.jar lib/Dictionary
【解决方案2】:

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

但是,如果您真的需要File,那么您最好尝试以下方法:

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

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

【讨论】:

    【解决方案3】:

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

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

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

    然后您可以访问 textfile.txt(正如 Mark 正确提到的):

    // 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");
    

    【讨论】:

      猜你喜欢
      • 2014-09-11
      • 1970-01-01
      • 2016-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多