จะอ่านไฟล์จากโฟลเดอร์ทรัพยากรใน 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

คำตอบ:


201

ทรัพยากรใน Scala ทำงานเหมือนกับที่ทำใน Java ที่ดีที่สุดคือทำตามJava ปฏิบัติที่ดีที่สุดและนำทรัพยากรทั้งหมดในและsrc/main/resourcessrc/test/resources

ตัวอย่างโครงสร้างโฟลเดอร์:

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

Scala 2.12.x && 2.13.x อ่านทรัพยากร

หากต้องการอ่านทรัพยากรวัตถุมาให้วิธีการfromResource

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

อ่านทรัพยากรก่อน 2.12 (ยังคงเป็นที่ชื่นชอบเนื่องจากความเข้ากันได้ของ jar)

หากต้องการอ่านทรัพยากรที่คุณสามารถใช้getClass.getResourceและgetClass.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ยังทำงานได้ดีเมื่อทรัพยากรเป็นส่วนหนึ่งของjar , getResourceซึ่งส่งคืน URL ที่มักใช้ในการสร้างไฟล์อาจทำให้เกิดปัญหาได้

ในการผลิต

ในรหัสการผลิตฉันขอแนะนำให้ตรวจสอบให้แน่ใจว่าแหล่งที่มาถูกปิดอีกครั้ง


ปัญหาประเภทใดที่อาจเกิดขึ้นหากใช้ getResource และเปลี่ยนเป็นไฟล์ คุณสามารถให้ลิงค์ได้หรือไม่?
akauppi

2
ในบางกรณีเป็น null Pointer: stackoverflow.com/questions/941754/…
Andreas Neumann

โค้ดนี้น่าจะออกจาก open handler สำหรับ getResourceAsStream
Sisso

3
อย่าลืมcloseแหล่งที่มา
Guillaume Massé

1
ขอบคุณ! คอนประเภทไม่ตรงกับในNicer ข้อเสนอแนะข้อผิดพลาด (2.12.x)ส่วน แล้วความจำรั่วล่ะ? ไม่ควรปิดทรัพยากร?
Albert Bikeev

30

สำหรับ Scala> = 2.12 ให้ใช้Source.fromResource:

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

13
สำคัญ: กับคุณไม่ใส่ทับเริ่มต้นที่คุณมีกับSource.fromResource getResourceAsStream
vossad01

6
และสังเกตว่านี่คือ
2.12+

แล้วเวอร์ชัน 2.10 ล่ะ?
Jaydev


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 ไปยังระบบไฟล์ภายในเครื่องได้

นี่คือ snippit ที่อ่านไบนารี google ที่สำคัญรูปแบบ p12 ที่ API จากทรัพยากร / เขียนมัน / tmp แล้วใช้สตริงเส้นทางของไฟล์เป็น input เพื่อหนึ่งจุดประกาย-google-สเปรดชีต เขียน

ในโลกของsbt-native-packagerและsbt-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}")

2

ไฟล์ที่ต้องการสามารถเข้าถึงได้จากโฟลเดอร์ทรัพยากรใน scala

val file = scala.io.Source.fromFile(s"src/main/resources/app.config").getLines().mkString
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.