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

4

我写了以下代码来从资源目录读取文件:

val filePath = MyClass.getClass.getResource("/myFile.csv")
val file = filePath.getFile
println(file)
CSVReader.open(file)

我得到的结果大致如下:

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)

如果我在IDE(Intellij)中运行相同的代码,没有问题,控制台打印的路径为:

/path/to/project/my_module/target/scala-2.11/classes/myFile.csv

提供信息,这是一个由几个模块组成的多构建项目,使用sbt assembly构建jar包。

1个回答

8

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

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

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

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


由于您想要读取文件的内容,您可能希望使用getClass.getResourceAsStream(...)。这将为您提供一个InputStream,无论您在IDE中还是其他任何地方,都可以使用它来读取内容。
您的CSVReader类可能有一种方法,允许它从InputStreamReader或类似的东西中读取数据。 编辑:如Luis Miguel Mejia Suarez所指出的那样,从您的类路径中读取文件的更Scala惯用的方法是使用Source.fromResource方法。这将返回一个BufferedSource,然后可以用它来读取文件内容。

3
@AlonsoDominguez 回答很棒!不过有一个注释,在Scala中我们有Source类上的fromResource 方法,可以读取资源的内容-在我看来,您可以更新答案,使用它代替getClass.getResourceAsStream,因为后者更适用于Java。 - Luis Miguel Mejía Suárez
1
@LuisMiguelMejíaSuárez 说得好,我会把它作为一个附注添加进去,因为我们不知道CSVReader API的外观,可能无法从Scala BufferedSource中读取数据。 - Alonso Dominguez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接