【问题标题】:How can i read files from src/main/resources with the java.io.File class? [duplicate]如何使用 java.io.File 类从 src/main/resources 读取文件? [复制]
【发布时间】:2014-09-04 10:59:06
【问题描述】:

我有一个 maven 项目,它的资源打包在 src/main/resources 中。该依赖项使用 weka 库,特别是 AddClassification class,它在其 AddClassification.setOptions() 方法中使用 java.io.FILE 类来读取给定的模型文件。 也许同样重要的是要注意这个项目是其他 maven 项目的依赖项,最终它将被运行在 apache-tomcat 中的 Web 应用程序使用。

为澄清起见,方法AddClassification.setOptions() 是这样调用的:

AddClassification filter = new AddClassification();
filter.setInputFormat(labeled);
String[] options = new String[3];
options[0] = "-serialized";
options[1] = "models/trained.model";
options[2] = "-classification";
filter.setOptions(options);

所以,归结为我的问题和需求:

  • 我需要将文件路径字符串传递给AddClassification.setOptions()
  • 我需要使用 weka 库,因为这个小依赖不是我自己编写的;
  • 所有模型文件都应该在 Jar 文件 (src/main/resources) 中,以便于分发;
  • java.io.File 不会直接读取 Jar 文件中的文件(我查过了);
  • 我知道class.getResourceAsStream 可以很好地解决这个问题,但是 weka 库需要一个字符串参数来使用java.io.File

我该如何解决这个问题?我可以轻松地将所有资源复制到硬编码的系统目录,但这会使我的项目难以分发到其他系统。 我正在寻找解决问题的正确方法。

我希望我说得够清楚。

【问题讨论】:

  • 你不能,依赖于这样实现的库的编写和设计都很糟糕

标签: java maven weka


【解决方案1】:

查看代码,我能看到实现它的最简单方法是继承AddClassification 并覆盖受保护的getActualClassifier 方法以从getResourceAsStream 加载您的分类器。令人讨厌的是,您仍然必须确保将一个绝对存在的文件的路径传递给setOptions,否则它会抱怨,但您可能能够摆脱/dev/null/bin/sh 之类的东西,因为您没有需要从文件中实际读取,它必须存在。

AddClassification filter = new AddClassification() {
  protected Classifier getActualClassifier() {
    ObjectInputStream   ois;

    if (m_ActualClassifier == null) {
      try {
        ois = new ObjectInputStream(
                     this.getClass().getResourceAsStream("classifier.ser"));
        m_ActualClassifier = (Classifier) ois.readObject();
        m_SerializedHeader = null;
        // let's see whether there's an Instances header stored as well
        try {
          m_SerializedHeader = (Instances) ois.readObject();
        }
        catch (Exception e) {
          // ignored
          m_SerializedHeader = null;
        }
        ois.close();
      }
      catch (Exception e) {
        m_ActualClassifier = null;
        System.err.println("Failed to instantiate classifier:");
        e.printStackTrace();
      }
    }

    return m_ActualClassifier;
  }
};

filter.setInputFormat(labeled);
String[] options = new String[3];
options[0] = "-serialized";
options[1] = "/dev/null";
options[2] = "-classification";
filter.setOptions(options);

【讨论】:

    【解决方案2】:

    您始终可以将资源复制到临时文件中:

    Path file = Files.createTempFile(null, null);
    
    try (InputStream stream =
        MyOwnClass.class.getResourceAsStream("models/trained.model")) {
    
        Files.copy(stream, file, StandardCopyOption.REPLACE_EXISTING);
    }
    
    options[1] = file.toString();
    

    【讨论】:

      【解决方案3】:

      请尝试一下

      AddClassification filter = new AddClassification();
      filter.setInputFormat(labeled);
      String[] options = new String[3];
      options[0] = "-serialized";
      options[1] =  this.getClass().getResource("/models/trained.model").getFile();
      options[2] = "-classification";
      filter.setOptions(options);
      

      【讨论】:

      • URL.getFile() 返回文件名。它返回 URL 的路径部分,其中可能包含转义的八位字节,因此不能保证与现有文件路径相对应。该方法之所以命名为 getFile(),是因为 URL 类非常古老,实际上是 Java 1.0 的一部分,而且在当时,URL 经常引用物理文件(例如 ftp: URLs)。比较 new URL("file:/C:/Program%20Files/Microsoft")new File("C:\\Program Files\\Microsoft")
      猜你喜欢
      • 2015-02-26
      • 2014-04-01
      • 2015-09-16
      • 1970-01-01
      • 1970-01-01
      • 2015-03-22
      • 2017-02-10
      • 2015-04-18
      相关资源
      最近更新 更多