Comment lire des fichiers à partir du dossier de ressources dans Scala?

112

J'ai une structure de dossiers comme ci-dessous:

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

et dans ces dossiers, j'ai mes fichiers que je dois lire. Voici le 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
la source
pourquoi la réponse d'Andreas Neumann n'a pas été acceptée si vous avez des questions complémentaires, veuillez la commenter. -1.
Vishrant

Réponses:

201

Les ressources de Scala fonctionnent exactement comme elles le font en Java. Il est préférable de suivre les meilleures pratiques Java et de mettre toutes les ressources dans src/main/resourceset src/test/resources.

Exemple de structure de dossier:

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

Scala 2.12.x && 2.13.x lecture d'une ressource

Pour lire les ressources, l'objet Source fournit la méthode fromResource .

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

lecture des ressources antérieures à 2.12 (toujours mon préféré en raison de la compatibilité des jar)

Pour lire les ressources, vous pouvez utiliser getClass.getResource et getClass.getResourceAsStream .

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

meilleur retour d'erreur (2.12.x && 2.13.x)

Pour éviter les NPE Java non déboguables, pensez à:

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

bon à savoir

Gardez à l'esprit que getResourceAsStream fonctionne également correctement lorsque les ressources font partie d'un fichier jar , getResource , qui renvoie une URL souvent utilisée pour créer un fichier peut entraîner des problèmes.

en production

Dans le code de production, je suggère de m'assurer que la source est à nouveau fermée.

Andreas Neumann
la source
Quels types de problèmes peuvent survenir si vous utilisez getResource et que vous le transformez en fichier? Pouvez-vous fournir un lien?
akauppi
2
Dans certaines circonstances, un pointeur nul: stackoverflow.com/questions/941754/…
Andreas Neumann
Ce code laisse probablement le gestionnaire ouvert pour getResourceAsStream.
Sisso le
3
n'oubliez pas à closela source
Guillaume Massé
1
Merci! Les types d' octets ne correspondent pas dans la section Nicer error feedback (2.12.x) . Et qu'en est-il des fuites de mémoire? La ressource ne devrait-elle pas être fermée?
Albert Bikeev
30

Pour Scala> = 2.12, utilisez Source.fromResource:

scala.io.Source.fromResource("located_in_resouces.any")
Mohsen Kashi
la source
13
Important: avec Source.fromResourcevous ne mettez pas la barre oblique initiale que vous avez avec getResourceAsStream.
vossad01
6
Et notez que c'est 2.12+
rbellamy
qu'en est-il des versions 2.10?
Jaydev
12

Solution Onliner pour Scala> = 2.12

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

  }

}

entrez la description de l'image ici

EDIT: Crédit à l'auteur original. Reportez-vous au blog complet ici

Sri
la source
Lorsque vous copiez à partir d'un site Web, veuillez publier un lien vers l'auteur original. Donnez du crédit là où il est dû. Reportez-vous: fruzenshtein.com/scala-working-with-resources-folders-files
ForeverLearner
2

Pour Scala 2.11 , si getLines ne fait pas exactement ce que vous voulez, vous pouvez également copier le fichier a du jar vers le système de fichiers local.

Voici un extrait de code qui lit une clé d'API au format binaire google .p12 à partir de / resources, l'écrit dans / tmp, puis utilise la chaîne de chemin de fichier comme entrée pour une écriture de spark-google-spreadsheets .

Dans le monde de sbt-native-packager et sbt-assembly , la copie en local est également utile avec les tests de fichiers binaires scalatest. Faites-les simplement sortir des ressources en local, exécutez les tests, puis supprimez-les.

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
la source
2

Le fichier requis est accessible comme ci-dessous à partir du dossier de ressources dans scala

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