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
    }
  }
}
Pradip Karad
sumber
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.

Andreas Neumann
sumber
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")
Mohsen Kashi
sumber
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
freedev
sumber
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

Sri
sumber
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}")
Tony Fraser
sumber
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
Dileep Dominic
sumber