Bagaimana cara membaca file dari folder sumber di Scala?


112

Saya memiliki struktur folder seperti di bawah ini:

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

dan di folder itu saya memiliki file yang harus saya baca. Ini kodenya:

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

mengapa jawaban yang diberikan oleh Andreas Neumann tidak diterima jika ada pertanyaan lanjutan silahkan dikomentari. -1.
Vishrant

Jawaban:


201

Sumber daya di Scala berfungsi persis seperti di Java. Yang terbaik adalah mengikuti praktik terbaik Java dan memasukkan semua sumber daya ke dalam src/main/resourcesdan src/test/resources.

Contoh struktur folder:

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

Scala 2.12.x && 2.13.x membaca sumber daya

Untuk membaca sumber daya, Sumber objek menyediakan metode fromResource .

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

membaca sumber daya sebelum 2.12 (masih favorit saya karena kompatibilitas jar)

Untuk membaca sumber daya, Anda dapat menggunakan getClass.getResource dan getClass.getResourceAsStream .

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

umpan balik kesalahan yang lebih baik (2.12.x && 2.13.x)

Untuk menghindari Java NPE yang tidak dapat dibundel, pertimbangkan:

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

senang mendengarnya

Perlu diingat bahwa getResourceAsStream juga berfungsi dengan baik jika resource merupakan bagian dari jar , getResource , yang menampilkan URL yang sering digunakan untuk membuat file dapat menyebabkan masalah di sana.

dalam produksi

Dalam kode produksi, saya sarankan untuk memastikan bahwa sumber ditutup lagi.


Jenis masalah apa yang dapat terjadi jika menggunakan getResource dan mengubahnya menjadi File? Dapatkah Anda menyediakan sebuah sambungan?
akauppi

2
Dalam beberapa keadaan sebagai Pointer nol: stackoverflow.com/questions/941754/…
Andreas Neumann

Kode ini mungkin meninggalkan handler terbuka untuk getResourceAsStream.
Sisso

3
jangan lupa ke closeSumber
Guillaume Massé

1
Terima kasih! Jenis byte tidak cocok di bagian Umpan balik kesalahan yang lebih bagus (2.12.x) . Dan bagaimana dengan kebocoran memori? Bukankah sumber daya harus ditutup?
Albert Bikeev

30

Untuk Scala> = 2.12, gunakan Source.fromResource:

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

13
Penting: dengan Source.fromResourceAnda jangan memasukkan garis miring awal yang Anda miliki getResourceAsStream.
vossad01

6
Dan perhatikan bahwa ini adalah 2.12+
rbellamy

bagaimana dengan versi 2.10?
Jaydev

12

Solusi onliner untuk 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 fileStream = getClass.getResourceAsStream("/json-sample.js")
    val lines = Source.fromInputStream(fileStream).getLines
    lines.foreach(line => println(line))

  }

}

masukkan deskripsi gambar di sini

EDIT: Penghargaan untuk penulis asli. Lihat blog lengkapnya di sini


Saat Anda menyalin dari situs web, harap posting tautan ke penulis aslinya. Berikan kredit di tempat yang seharusnya. Lihat: fruzenshtein.com/scala-working-with-resources-folders-files
ForeverLearner

2

Untuk Scala 2.11 , jika getLines tidak melakukan apa yang Anda inginkan, Anda juga dapat menyalin file dari jar ke sistem file lokal.

Berikut cuplikan yang membaca kunci API format google .p12 biner dari / resources, menuliskannya ke / tmp, lalu menggunakan string jalur file sebagai masukan untuk penulisan spark-google-spreadsheets .

Dalam dunia sbt-native-packager dan sbt-assembly , menyalin ke lokal juga berguna dengan tes file biner scalatest. Cukup keluarkan mereka dari sumber daya ke lokal, jalankan tes, lalu hapus.

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

File yang dibutuhkan dapat diakses seperti di bawah ini dari folder sumber daya dalam skala

val file = scala.io.Source.fromFile(s"src/main/resources/app.config").getLines().mkString
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.