从资源目录读取文件的Scala问题

Dev*_*vEx 1 scala sbt

我写了这样的东西来从资源目录中读取文件:

val filePath = MyClass.getClass.getResource("/myFile.csv")
val file = filePath.getFile
println(file)
CSVReader.open(file)
Run Code Online (Sandbox Code Playgroud)

我得到的结果是这样的:

file:/path/to/project/my_module/src/main/resources/my_module-assembly-0.1.jar!/myFile.csv

Exception in thread "main" java.io.FileNotFoundException: file:/path/to/project/my_module/src/main/resources/my_module-assembly-0.1.jar!/myFile.csv (No such file or directory)
Run Code Online (Sandbox Code Playgroud)

然而,如果我在 IDE(Intellij)中运行相同的代码,则没有问题,并且打印到控制台的路径是:

/path/to/project/my_module/target/scala-2.11/classes/myFile.csv
Run Code Online (Sandbox Code Playgroud)

仅供参考,它是一个包含几个模块的多构建项目,我使用 sbt assembly

Alo*_*uez 5

这更多地与 Java 或 JVM 本身相关,而不是与 Scala 或 SBT 相关。

从 IDE 与命令行(或在 IDE 外部)运行应用程序时存在差异。该方法getClass.getResource(...)尝试在当前类路径中查找资源 URL ,这是关键区别。

如果您查看 URL 本身,您会发现在第一种情况下您有my_module-assembly-0.1.jar!一些内容,这意味着 URL 实际上指向 JAR 的内容,而不是可从文件系统访问的文件。

从您的 IDE 内部,您的类路径将包括磁盘上的实际文件,来自源文件夹,因为 IDE 假定没有任何 JAR 文件本身。因此,当获取getClass.getResource(...)您给出的 URL 时,您的 URL 中没有该my_module-assembly-0.1.jar!位。


由于您想读取文件的内容,您可能需要执行getClass.getResourceAsStream(...). 这会给你的InputStream,你可以用它来阅读的内容,无论你是在IDE中或其他地方。

您的CSVReader类可能有一个方法,允许它从 anInputStream或 aReader或类似的东西读取数据。

编辑:正如 Luis Miguel Mejia Suarez所指出的,从类路径中读取文件的更 Scala 惯用方法是使用Source.fromResource方法. 这将返回一个BufferedSource,然后可用于读取文件内容。

  • @AlonsoDominguez 很好的答案!但是请注意,在 Scala 中,我们有 [`fromResource` _method_](https://www.scala-lang.org/api/current/scala/io/Source$.html#fromResource(resource:String,classLoader:ClassLoader )(implicitcodec:scala.io.Codec):scala.io.BufferedSource) 在 **Source** 类上读取资源的内容 - 恕我直言,您可以更新答案以使用它而不是`getClass.getResourceAsStream`这是更多的Java。 (3认同)