jjzjj

java - 检索子包类的资源

coder 2024-03-20 原文

我使用 Java 的时间不长,所以我不确定还需要寻找什么。我希望有人能指出我正确的方向。

目标: 我想使用一个查找表,存储为一个文本文件。但我不想使用绝对路径,因为最后我想打包一个版本并能够从任何位置调用它(文本文件将包含在打包版本中)。

当前设置: 我将文本文件放在一个名为“resources”的文件夹中(因为通过阅读有关 java 的教程,我得到的印象是,我应该把它放在这里以维护结构更好的项目)。

在根包文件夹中,我有一个类 (MainClass.java) 正在调用子包中的另一个类 (LookUpClass.java)。 文件夹设置如下:

  • 来源
    • java
      • main.package.com
        • 分包
          • 查找类.java
          • PlotterClass.java
        • 主类.java
    • 资源
      • 查找表
        • LookUpTable1.txt
        • LookUpTable2.txt

我在 LookUpClass.java 中编写了一个方法,它从资源中的查找表中检索特定行。为了检索文件并读出某一行,我使用了

// Gets respective line from LUT
private static String getLineFromLUT(int line) {
    URL url = LookUpClass.class.getClass().getResource("/LookUpTables/LookUpTable1.txt");
    File file = new File(url.toURI());
    BufferedReader br = new BufferedReader(new FileReader(file));

    for (int i = 0; i < line; ++i)
        br.readLine();

    return br.readLine;
}

在我的项目结构中,“java”文件夹被标记为“source”,而“resources”被标记为“resources”。

我的测试设置非常简单:

public static void main(String[] args) throws URISyntaxException, IOException {
    String c = LookUpClass.getLineFromLUT(5);
    System.out.println("Color of line 5: " + c);
}

输出:

Color of line 5: 0  0   38

(这是正确的。)

我向 PlotterClass.java 添加了完全相同的行,它也工作正常。

问题:

现在,如果我在 MainClass.java 中尝试相同的操作,我会收到一个错误,其中 url 为 null。似乎找不到资源/资源文件夹。

我已经阅读了关于 SO 的各种帖子并尝试了几个建议的解决方案,但到目前为止都失败了:

  • 如果使用 LookUpClass.class.getClassLoader().getResource("/LookUpTables/LookUpTable1.txt")MainClass.javaLookUpClass 调用。 java 失败(url 为空)。
  • 我尝试使用以下路径(所有路径都不适用于任何一个类): “LookUpTables/LookUpTable1.txt”(删除开头“/”) “/subpackage/LookUpTables/LookUpTable1.txt” “../subpackage/LookUpTables/LookUpTable1.txt”
  • 自从使用 Idea IntelliJ 以来,我检查了“设置 > 构建、执行、部署 > 编译器 > 资源模式”并将“*.txt”添加到模式中。没有任何变化。
  • 如果添加 Class c = LookUpClass.class.getClass();,在 Debug模式下 c 是“class.java.lang.Class”。我期待的是“main.package.com.subpackage.LookUpClass”之类的东西。
  • 有时我尝试使用 getResourceAsStream(),但我不明白如何获取(例如)第 5 行,所以我放弃了它。如果它能解决我的问题,我愿意继续阅读。

我不知道如何解决这个问题。我意识到在这一点上我只是在尝试一些东西,甚至不明白为什么它可以或不能工作。 对我来说,LookUpClass.java 似乎是从与 MainClass.java 不同的位置运行的。但是“资源”文件夹和相应的文本文件位置永远不会改变。如何在一种情况下找到文件,而在另一种情况下找不到文件?

最佳答案

Maven 有一个 standard directory layout . src/main/resources 目录就是为此类应用程序资源准备的。将您的文本文件放入其中。

您现在基本上有两个选项可以准确地放置您的文件:

  1. 资源文件属于一个类。

一个例子是代表 GUI 元素(面板)的类,它还需要显示一些图像。

在这种情况下,将资源文件放入与相应类相同的目录(包)中。例如。对于名为 your.pkg.YourClass 的类,将资源文件放入目录 your/pkg:

src/main
 +-- java/
 |    +-- your/pkg/
 |    |    +-- YourClass.java
 +-- resources/
      +-- your/pkg/
           +-- resource-file.txt

您现在通过相应的类加载资源。在 your.pkg.YourClass 类中,您有以下用于加载的代码片段:

String resource = "resource-file.txt"; // the "file name" without any package or directory
Class<?> clazz = this.getClass(); // or YourClass.class
URL resourceUrl = clazz.getResource(resource);
if (resourceUrl != null) {
    try (InputStream input = resourceUrl.openStream()) {
        // load the resource here from the input stream
    }
}

注意:您也可以通过类的类加载器加载资源:

String resource = "your/pkg/resource-file.txt";
ClassLoader loader = this.getClass().getClassLoader(); // or YourClass.class.getClassLoader()
URL resourceUrl = loader.getResource(resource);
if (resourceUrl != null) {
    try (InputStream input = resourceUrl.openStream()) {
        // load the resource here from the input stream
    }
}

选择你觉得更方便的。

  1. 资源整体属于应用。

在这种情况下,只需将资源直接放入 src/main/resources 目录或适当的子目录中。让我们看一个使用您的查找文件的示例:

src/main/resources/
    +-- LookupTables/
         +-- LookUpTable1.txt

然后您必须通过类加载器加载资源,使用当前线程的上下文类加载器或应用程序类加载器(无论哪个更合适 - 如果感兴趣,请搜索有关此问题的文章)。我将向您展示两种方式:

String resource = "LookupTables/LookUpTable1.txt";
ClassLoader ctxLoader = Thread.currentThread().getContextClassLoader();
ClassLoader sysLoader = ClassLoader.getSystemClassLoader();
URL resourceUrl = ctxLoader.getResource(resource); // or sysLoader.getResource(resource)
if (resourceUrl != null) {
    try (InputStream input = resourceUrl.openStream()) {
        // load the resource here from the input stream
    }
}

作为第一个建议,使用当前线程的上下文类加载器。在独立应用程序中,这将是系统类加载器或将系统类加载器作为父级。 (这些类加载器之间的区别对于同时加载资源的库来说将变得很重要。)

您应该始终使用类加载器来加载资源。通过这种方式,您可以独立于位置进行加载(只需注意在启动应用程序时文件位于类路径内),并且您可以将整个应用程序打包到一个仍然可以找到资源的 JAR 文件中。

关于java - 检索子包类的资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29413713/

有关java - 检索子包类的资源的更多相关文章

  1. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  2. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  3. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  4. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  5. 没有类的 Ruby 方法? - 2

    大家好!我想知道Ruby中未使用语法ClassName.method_name调用的方法是如何工作的。我头脑中的一些是puts、print、gets、chomp。可以在不使用点运算符的情况下调用这些方法。为什么是这样?他们来自哪里?我怎样才能看到这些方法的完整列表? 最佳答案 Kernel中的所有方法都可用于Object类的所有对象或从Object派生的任何类。您可以使用Kernel.instance_methods列出它们。 关于没有类的Ruby方法?,我们在StackOverflow

  6. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  7. ruby - Rails 关联 - 同一个类的多个 has_one 关系 - 2

    我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下

  8. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  9. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  10. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

随机推荐