如何从Scala的资源文件夹中读取文件?


112

我的文件夹结构如下:

- main
-- java
-- resources 
-- scalaresources
--- commandFiles 

在那个文件夹中,我必须读取文件。这是代码:

def readData(runtype: String, snmphost: String, comstring: String, specificType:  String): Unit = {
  val realOrInvFile = "/commandFiles/snmpcmds." +runtype.trim // these files are under commandFiles folder, which I have to read. 
    try {
      if (specificType.equalsIgnoreCase("Cisco")) {
        val specificDeviceFile: String = "/commandFiles/snmpcmds."+runtype.trim+ ".cisco"
        val realOrInvCmdsList = scala.io.Source.fromFile(realOrInvFile).getLines().toList.filterNot(line => line.startsWith("#")).map{
          //some code 
        }
        val specificCmdsList = scala.io.Source.fromFile(specificDeviceFile).getLines().toList.filterNot(line => line.startsWith("#")).map{
          //some code
        }
      }
    } catch {
      case e: Exception => e.printStackTrace
    }
  }
}

如果您有任何后续问题,为什么不接受Andreas Neumann提供的答案,请对此发表评论。-1。
Vishrant

Answers:


201

Scala中的资源与Java中的资源完全一样。最好遵循Java最佳实践并将所有资源都放在src/main/resources和中src/test/resources

文件夹结构示例:

testing_styles/
├── build.sbt
├── src
│   └── main
│       ├── resources
│       │   └── readme.txt

Scala 2.12.x && 2.13.x读取资源

要读取资源,对象Source提供了fromResource方法。

import scala.io.Source
val readmeText : Iterator[String] = Source.fromResource("readme.txt").getLines

在2.12之前的版本中阅读资源(由于jar的兼容性,我仍然很喜欢)

要读取资源,可以使用getClass.getResourcegetClass.getResourceAsStream

val stream: InputStream = getClass.getResourceAsStream("/readme.txt")
val lines: Iterator[String] = scala.io.Source.fromInputStream( stream ).getLines

更好的错误反馈(2.12.x && 2.13.x)

为避免不可辩驳的Java NPE,请考虑:

import scala.util.Try
import scala.io.Source
import java.io.FileNotFoundException

object Example {

  def readResourceWithNiceError(resourcePath: String): Try[Iterator[String]] = 
    Try(Source.fromResource(resourcePath).getLines)
      .recover(throw new FileNotFoundException(resourcePath))
 }

很高兴知道

记住的getResourceAsStream也工作正常时,资源是一部分罐子的getResource,它返回它经常被用来创建一个文件可能会导致问题出现的URL。

生产中

在生产代码中,我建议确保再次关闭源。


如果使用getResource并将其转换为File,会发生什么样的问题?你能提供一个链接吗?
akauppi '16

2
在一些circumstanceas一个空指针:stackoverflow.com/questions/941754/...
安德烈亚斯·诺依曼

这段代码可能会为getResourceAsStream留下开放处理程序。
Sisso

3
不要忘close了消息源
GuillaumeMassé'Feb 15'17

1
谢谢!字节类型在Niceer错误反馈(2.12.x)部分中不匹配。那内存泄漏呢?资源不应该关闭吗?
艾伯特·比基耶夫

30

对于Scala> = 2.12,请使用Source.fromResource

scala.io.Source.fromResource("located_in_resouces.any")

13
重要提示:Source.fromResource不要随身携带斜线getResourceAsStream
vossad01 2016年

6
请注意,这是2.12+
rbellamy

那2.10版本呢?
Jaydev

11

Scala Onliner解决方案> = 2.12

val source_html = Source.fromResource("file.html").mkString

4
import scala.io.Source

object Demo {

  def main(args: Array[String]): Unit = {

    val fileStream = getClass.getResourceAsStream("/json-sample.js")
    val lines = Source.fromInputStream(fileStream).getLines
    lines.foreach(line => println(line))

  }

}

在此处输入图片说明

编辑:感谢原始作者。在这里参考完整的博客


从网站复制时,请发布原始作者的链接。在适当的时候给予信用。请参阅:fruzenshtein.com/scala-working-with-resources-folders-files
ForeverLearner

2

对于Scala 2.11,如果getLines不能完全满足您的要求,您还可以将文件从jar中复制到本地文件系统中。

这是一个片段,它从/ resources读取一个google .p12格式的二进制API密钥,将其写入/ tmp,然后将文件路径字符串用作spark-google-spreadsheets write的输入。

sbt-native-packagersbt-assembly的世界中,复制到本地对于scalatest二进制文件测试也很有用。只需将它们从资源中弹出到本地,运行测试,然后删除即可。

import java.io.{File, FileOutputStream}
import java.nio.file.{Files, Paths}

def resourceToLocal(resourcePath: String) = {
  val outPath = "/tmp/" + resourcePath
  if (!Files.exists(Paths.get(outPath))) {
    val resourceFileStream = getClass.getResourceAsStream(s"/${resourcePath}")
    val fos = new FileOutputStream(outPath)
    fos.write(
      Stream.continually(resourceFileStream.read).takeWhile(-1 !=).map(_.toByte).toArray
    )
    fos.close()
  }
  outPath
}

val filePathFromResourcesDirectory = "google-docs-key.p12"
val serviceAccountId = "[something]@drive-integration-[something].iam.gserviceaccount.com"
val googleSheetId = "1nC8Y3a8cvtXhhrpZCNAsP4MBHRm5Uee4xX-rCW3CW_4"
val tabName = "Favorite Cities"

import spark.implicits
val df = Seq(("Brooklyn", "New York"), 
          ("New York City", "New York"), 
          ("San Francisco", "California")).
          toDF("City", "State")

df.write.
  format("com.github.potix2.spark.google.spreadsheets").
  option("serviceAccountId", serviceAccountId).
  option("credentialPath", resourceToLocal(filePathFromResourcesDirectory)).
  save(s"${googleSheetId}/${tabName}")

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.