Wie lese ich Dateien aus dem Ressourcenordner in Scala?

112

Ich habe eine Ordnerstruktur wie folgt:

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

und in diesen Ordnern habe ich meine Dateien, die ich lesen muss. Hier ist der Code:

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
quelle
Warum die Antwort von Andreas Neumann nicht akzeptiert wurde, wenn Sie weitere Fragen haben, kommentieren Sie diese bitte. -1.
Vishrant

Antworten:

201

Ressourcen in Scala funktionieren genauso wie in Java. Befolgen Sie am besten die Best Practices von Java und setzen Sie alle Ressourcen in src/main/resourcesund ein src/test/resources.

Beispiel Ordnerstruktur:

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

Scala 2.12.x && 2.13.x Lesen einer Ressource

Zum Lesen von Ressourcen stellt das Objekt Source die Methode fromResource bereit .

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

Lesen von Ressourcen vor 2.12 (immer noch mein Favorit aufgrund der JAR-Kompatibilität)

Zum Lesen von Ressourcen können Sie getClass.getResource und getClass.getResourceAsStream verwenden .

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

schönere Fehlerrückmeldung (2.12.x && 2.13.x)

Beachten Sie Folgendes, um nicht debuggbare Java-NPEs zu vermeiden:

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

gut zu wissen

Beachten Sie, dass getResourceAsStream auch gut funktioniert , wenn die Ressourcen Teil eines sind Glas , getResource , die eine URL zurück , die oft eine Datei erstellen verwendet wird , kann es zu Problemen führen.

in Produktion

Im Produktionscode schlage ich vor, sicherzustellen, dass die Quelle wieder geschlossen wird.

Andreas Neumann
quelle
Welche Probleme können auftreten, wenn getResource verwendet und in eine Datei umgewandelt wird? Können Sie einen Link bereitstellen?
Akauppi
2
Unter bestimmten Umständen ein Nullzeiger: stackoverflow.com/questions/941754/…
Andreas Neumann
Dieser Code lässt wahrscheinlich den Handler für getResourceAsStream offen.
Sisso
3
Vergessen Sie nicht closedie Quelle
Guillaume Massé
1
Vielen Dank! Byt-Typen stimmen im Abschnitt " Schönere Fehlerrückmeldung (2.12.x)" nicht überein . Und was ist mit Speicherlecks? Sollte die Ressource nicht geschlossen werden?
Albert Bikeev
30

Verwenden Sie für Scala> = 2.12 Source.fromResource:

scala.io.Source.fromResource("located_in_resouces.any")
Mohsen Kashi
quelle
13
Wichtig: Setzen Source.fromResourceSie bei Ihnen nicht den anfänglichen Schrägstrich, den Sie haben getResourceAsStream.
Vossad01
6
Und beachten Sie, dass dies 2.12+ ist
Rbellamy
Was ist mit den Versionen 2.10?
Jaydev
11

Onliner-Lösung für Scala> = 2.12

val source_html = Source.fromResource("file.html").mkString
freedev
quelle
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))

  }

}

Geben Sie hier die Bildbeschreibung ein

EDIT: Gutschrift an den ursprünglichen Autor. Den vollständigen Blog finden Sie hier

Sri
quelle
Wenn Sie von einer Website kopieren, veröffentlichen Sie bitte einen Link zum ursprünglichen Autor. Geben Sie Kredit, wo es fällig ist. Siehe: fruzenshtein.com/scala-working-with-resources-folders-files
ForeverLearner
2

Für Scala 2.11 , wenn getLines nicht genau das tun , was Sie wollen Sie auch die eine Datei aus dem Glas in dem lokalen Dateisystem kopieren.

Hier ist ein Snippit, der einen binären API-Schlüssel im Google .p12-Format aus / resources liest, in / tmp schreibt und dann die Dateipfadzeichenfolge als Eingabe für einen Schreibvorgang für Spark-Google-Tabellen verwendet .

In der Welt des sbt-native-Packagers und der sbt-Assembly ist das Kopieren nach local auch bei skalierten Binärdateitests nützlich. Pop sie einfach aus den Ressourcen zu lokal, führen Sie die Tests aus und löschen Sie dann.

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
quelle
2

Auf die erforderliche Datei kann wie folgt aus dem Ressourcenordner in Scala zugegriffen werden

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