Come leggere i file dalla cartella delle risorse in Scala?


112

Ho una struttura di cartelle come di seguito:

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

e in quelle cartelle ho i miei file che devo leggere. Ecco il codice:

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

perché la risposta fornita da Andreas Neumann non è stata accettata se hai qualche domanda di follow-up, ti preghiamo di commentarla. -1.
Vishrant

Risposte:


201

Le risorse in Scala funzionano esattamente come in Java. È meglio seguire le migliori pratiche Java e inserire tutte le risorse in src/main/resourcese src/test/resources.

Esempio di struttura di cartelle:

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

Scala 2.12.x && 2.13.x leggendo una risorsa

Per leggere le risorse l'oggetto Source fornisce il metodo fromResource .

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

risorse di lettura precedenti alla 2.12 (ancora le mie preferite a causa della compatibilità con jar)

Per leggere le risorse puoi utilizzare getClass.getResource e getClass.getResourceAsStream .

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

feedback di errore migliore (2.12.x && 2.13.x)

Per evitare NPE Java non debuggabili, considerare:

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

buono a sapersi

Tieni presente che getResourceAsStream funziona bene anche quando le risorse fanno parte di un jar , getResource , che restituisce un URL che viene spesso utilizzato per creare un file può causare problemi lì.

in produzione

Nel codice di produzione suggerisco di assicurarmi che il sorgente sia nuovamente chiuso.


Che tipo di problemi potrebbero verificarsi se si utilizza getResource e lo si trasforma in un file? Puoi fornire un collegamento?
akauppi

2
In alcune circostanze come un puntatore nullo: stackoverflow.com/questions/941754/…
Andreas Neumann

Questo codice probabilmente sta lasciando il gestore aperto per getResourceAsStream.
Sisso

3
non dimenticare di The closeSource
Guillaume Massé

1
Grazie! I tipi di byte non corrispondono nella sezione Feedback di errore più bello (2.12.x) . E le perdite di memoria? La risorsa non dovrebbe essere chiusa?
Albert Bikeev

30

Per Scala> = 2.12, usa Source.fromResource:

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

13
Importante: con Source.fromResourcete non mettere la barra in avanti iniziale che hai con getResourceAsStream.
vossad01

6
E nota che questo è 2.12+
rbellamy

che dire delle versioni 2.10?
Jaydev

12

Soluzione online per 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))

  }

}

inserisci qui la descrizione dell'immagine

EDIT: credito all'autore originale. Fare riferimento al blog completo qui


Quando si copia da un sito Web, inviare un collegamento all'autore originale. Dai credito dove è dovuto. Fare riferimento: fruzenshtein.com/scala-working-with-resources-folders-files
ForeverLearner,

2

Per Scala 2.11 , se getLines non fa esattamente quello che vuoi, puoi anche copiare il file a dal jar nel file system locale.

Ecco uno snippit che legge una chiave API in formato binario google .p12 da / resources, la scrive in / tmp e quindi utilizza la stringa del percorso del file come input per una scrittura spark-google-spreadsheets .

Nel mondo di sbt-native-packager e sbt-assembly , la copia in locale è utile anche con i test di file binari più scalabili. Basta estrarli dalle risorse in locale, eseguire i test e quindi eliminare.

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

È possibile accedere al file richiesto come di seguito dalla cartella delle risorse in scala

val file = scala.io.Source.fromFile(s"src/main/resources/app.config").getLines().mkString
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.