¿Cómo leer archivos de la carpeta de recursos en Scala?

112

Tengo una estructura de carpetas como la siguiente:

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

y en esas carpetas tengo mis archivos que tengo que leer. Aquí está el código:

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
fuente
Por qué no se aceptó la respuesta proporcionada por Andreas Neumann si tiene alguna pregunta de seguimiento, por favor coméntela. -1.
Vishrant

Respuestas:

201

Los recursos en Scala funcionan exactamente como lo hacen en Java. Es mejor seguir las mejores prácticas de Java y poner todos los recursos en src/main/resourcesy src/test/resources.

Estructura de carpetas de ejemplo:

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

Scala 2.12.x && 2.13.x leyendo un recurso

Para leer recursos, el objeto Source proporciona el método fromResource .

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

leer recursos antes de la 2.12 (sigue siendo mi favorito debido a la compatibilidad con jar)

Para leer recursos, puede usar getClass.getResource y getClass.getResourceAsStream .

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

comentarios de error más agradables (2.12.xy& 2.13.x)

Para evitar NPE de Java no insegurables, considere:

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

bueno saber

Tenga en cuenta que getResourceAsStream también funciona bien cuando los recursos son parte de un jar , getResource , que devuelve una URL que se usa a menudo para crear un archivo y puede generar problemas allí.

en producción

En el código de producción, sugiero asegurarse de que la fuente esté cerrada nuevamente.

Andreas Neumann
fuente
¿Qué tipo de problemas podrían ocurrir si usa getResource y lo convierte en un archivo? ¿Puede proporcionar un enlace?
akauppi
2
En algunas circunstancias como un puntero nulo: stackoverflow.com/questions/941754/…
Andreas Neumann
Este código probablemente deja un controlador abierto para getResourceAsStream.
Sisso
3
no te olvides de closela Fuente
Guillaume Massé
1
¡Gracias! Los tipos de bytes no coinciden en la sección Comentarios de errores más agradables (2.12.x) . ¿Y las fugas de memoria? ¿No debería cerrarse el recurso?
Albert Bikeev
30

Para Scala> = 2.12, use Source.fromResource:

scala.io.Source.fromResource("located_in_resouces.any")
Mohsen Kashi
fuente
13
Importante: con Source.fromResourceusted no ponga la barra inclinada inicial que tiene getResourceAsStream.
vossad01
6
Y tenga en cuenta que esto es 2.12+
rbellamy
¿qué pasa con las versiones 2.10?
Jaydev
12

Solución en línea para Scala> = 2.12

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

  }

}

ingrese la descripción de la imagen aquí

EDITAR: Crédito al autor original. Consulte el blog completo aquí

Sri
fuente
Cuando copie desde un sitio web, publique un enlace al autor original. Dale crédito a lo que es debido. Consulte: fruzenshtein.com/scala-working-with-resources-folders-files
ForeverLearner
2

Para Scala 2.11 , si getLines no hace exactamente lo que usted desea, también puede copiar el archivo de la jarra con el sistema de archivos local.

Aquí hay un fragmento que lee una clave de API de formato binario google .p12 de / resources, la escribe en / tmp y luego usa la cadena de ruta del archivo como entrada para una escritura de spark-google-spreadsheets .

En el mundo de sbt-native- packager y sbt-assembly , copiar a local también es útil con las pruebas de archivos binarios más escalables. Simplemente sáquelos de los recursos a local, ejecute las pruebas y luego elimínelos.

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

Se puede acceder al archivo requerido como se muestra a continuación desde la carpeta de recursos en scala

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