【问题标题】:How to read files from resources folder in Scala?如何从 Scala 中的资源文件夹中读取文件?
【发布时间】:2018-04-05 21:52:34
【问题描述】:

我的文件夹结构如下:

- 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.

标签: scala scala-collections


【解决方案1】:

Scala 中的资源与 Java 中的资源完全一样。 最好遵循Java 最佳实践,并将所有资源放在src/main/resourcessrc/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))
 }

很高兴知道

请记住,当资源是 jar 的一部分时,getResourceAsStream 也可以正常工作,getResource 返回的 URL 通常是用于创建文件可能会导致出现问题。

生产中

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

【讨论】:

  • 如果使用getResource并将其转为文件会出现什么样的问题?能给个链接吗?
  • 在某些情况下作为空指针:stackoverflow.com/questions/941754/…
  • 此代码可能正在为 getResourceAsStream 保留打开的处理程序。
  • 别忘了close
  • 谢谢! 更好的错误反馈 (2.12.x) 部分中的字节类型不匹配。那么内存泄漏呢?不应该关闭资源吗?
【解决方案2】:

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

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

【讨论】:

  • 重要提示:Source.fromResource 不会像getResourceAsStream 那样使用初始正斜杠。
  • 并注意这是2.12+
  • 2.10 版本怎么样?
【解决方案3】:

Scala 的单线解决方案 >= 2.12

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

【讨论】:

    【解决方案4】:
    import scala.io.Source
    
    object Demo {
    
      def main(args: Array[String]): Unit = {
    
        val ipfileStream = getClass.getResourceAsStream("/folder/a-words.txt")
        val readlines = Source.fromInputStream(ipfileStream).getLines
        readlines.foreach(readlines => println(readlines))
    
      }
    
    }
    

    【讨论】:

    【解决方案5】:

    可以从scala的资源文件夹中访问所需的文件,如下所示

    val file = scala.io.Source.fromFile(s"src/main/resources/app.config").getLines().mkString
    

    【讨论】:

      【解决方案6】:

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

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

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

      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}")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-31
        • 1970-01-01
        • 2018-11-02
        • 2017-05-18
        • 2018-11-12
        • 2017-11-08
        • 2020-01-20
        相关资源
        最近更新 更多