【问题标题】:Read property file under classpath using scala使用scala读取类路径下的属性文件
【发布时间】:2013-02-13 03:43:34
【问题描述】:

我正在尝试使用 scala 从类路径中读取属性文件。但它看起来不起作用,它与java不同。下面2个代码sn-p,一个是java(工作),另一个是scala(不工作)。我不明白有什么区别。

// working
BufferedReader reader = new BufferedReader(new InputStreamReader(
Test.class.getResourceAsStream("conf/fp.properties")));

// not working 
val reader = new BufferedReader(new InputStreamReader(
getClass.getResourceAsStream("conf/fp.properties")));

Exception in thread "main" java.lang.NullPointerException
at java.io.Reader.<init>(Reader.java:78)
at java.io.InputStreamReader.<init>(InputStreamReader.java:72)
at com.ebay.searchscience.searchmetrics.fp.conf.FPConf$.main(FPConf.scala:31)
at com.ebay.searchscience.searchmetrics.fp.conf.FPConf.main(FPConf.scala)

【问题讨论】:

  • 你为什么不用Config
  • 得到了解决方案,我应该在这里使用绝对路径“/conf/fp.properties”,但仍然不清楚为什么相对路径在java中有效而在scala中无效

标签: scala classpath


【解决方案1】:

这段代码终于为我工作了:

import java.util.Properties
import scala.io.Source

// ... somewhere inside module.

var properties : Properties = null

val url = getClass.getResource("/my.properties")
if (url != null) {
    val source = Source.fromURL(url)

    properties = new Properties()
    properties.load(source.bufferedReader())
}

现在您有了普通的 java.util.Properties 来处理我的遗留代码实际需要接收的内容。

【讨论】:

  • link ** "指定的流在此方法返回后保持打开状态。" ** 所以你需要为其分配一个 tmp var,然后需要调用 close 以便文件描述符不泄露:val reader = source.bufferedReader()properties.load(reader)reader.close()
【解决方案2】:

我猜你的BufferedReaderjava.io.BufferedReader

在这种情况下,您只需执行以下操作:

import scala.io.Source.fromUrl
val reader = fromURL(getClass.getResource("conf/fp.properties")).bufferedReader()

但是,这留下了一个问题,即您计划在之后如何处理 readerscala.io.Source 已经有一些有用的方法可能会让你的很多代码变得多余.. see ScalaDoc

【讨论】:

  • 如果属性文件驻留在 jar 文件中(例如在资源目录中)怎么办?
  • From: val source = Source.fromURL(getClass.getResource("/conf/fp.properties"))
  • 这是更好的方法
  • 谢谢,但它仍然无法正常工作,同样的例外。我不知道为什么在这里找不到文件。
【解决方案3】:

我首选的解决方案是com.typesafe.scala-logging。我确实在 main\resources 文件夹中放了一个 application.conf 文件,内容如下:

services { mongo-db { retrieve = """http://xxxxxxxxxxxx""", base = """http://xxxxxx""" } }

要在类中使用它,首先从 typesafe 加载配置工厂,然后直接使用它。

val conf = com.typesafe.config.ConfigFactory.load() conf.getString("services.mongo-db.base"))

希望对你有帮助!

附言。我敢打赌,每个以 .conf 为扩展名的资源文件都会被读取。

【讨论】:

    【解决方案4】:

    对于读取属性文件,我建议使用java.util.ResourceBundle.getBundle("conf/fp"),它让生活更轻松。

    【讨论】:

      【解决方案5】:

      您看到的 NullPointerException 是由底层 Java 代码中的错误引起的。它可能是由错误输入的文件名引起的。

      如果您尝试使用错误的类加载器加载资源,有时也会出现此错误。

      1. 根据您的类路径仔细检查资源 url。
      2. 试试Source.fromInputStream(getClass.getResourceAsStream(...))
      3. 试试Source.fromInputStream(getClass.getClassLoader.getResourceAsStream())
      4. 也许您正在使用其他可以尝试的类加载器?

      Source.fromUrl(...) 也是如此

      如果您尝试加载配置文件并控制其格式,您应该查看 Typesafe 的 Config 实用程序。

      【讨论】:

        【解决方案6】:

        您得到的空指针异常来自 getResourceAsStream 返回空值。以下 junit.scala sn-p 显示了类与类加载器的区别。见What is the difference between Class.getResource() and ClassLoader.getResource()?。这里我假设fileName 是驻留在类路径中的文件的名称,而不是运行测试的类旁边的文件。

        assertTrue(getClass.getClassLoader().getResourceAsStream(fileName) != null)
        assertTrue(getClass.getClassLoader().getResourceAsStream("/" + fileName) == null)
        assertTrue(getClass.getResourceAsStream(fileName) == null)
        assertTrue(getClass.getResourceAsStream("/" + fileName) != null)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-10-12
          • 1970-01-01
          • 1970-01-01
          • 2021-01-05
          • 1970-01-01
          • 2013-08-30
          • 2012-01-29
          • 1970-01-01
          相关资源
          最近更新 更多