Як читати файли з папки ресурсів у Scala?


112

У мене структура папки, як показано нижче:

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

і в цих папках у мене є свої файли, які я маю прочитати. Ось код:

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

чому відповідь Андреаса Ноймана не була прийнята, якщо у вас є запитання, будь ласка, прокоментуйте їх. -1.
Вішрант

Відповіді:


201

Ресурси Scala працюють точно так само, як і в Java. Найкраще дотримуватися найкращих практик Java та вкладати всі ресурси в src/main/resourcesта src/test/resources.

Приклад структури папки:

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

Scala 2.12.x && 2.13.x читання ресурсу

Для зчитування ресурсів об'єкт Source забезпечує метод fromResource .

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

ресурси для читання до 2.12 (все ще мій улюблений через сумісність jar)

Для читання ресурсів можна використовувати getClass.getResource та getClass.getResourceAsStream .

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

приємніші відгуки про помилки (2.12.x та & 2.13.x)

Щоб уникнути нерозбірливих Java NPE Java, врахуйте:

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

добре знати

Майте на увазі, що getResourceAsStream також працює добре, коли ресурси є частиною банку , getResource , який повертає URL-адресу, яка часто використовується для створення файлу, може призвести до виникнення проблем.

у виробництві

У виробничому коді пропоную переконатися, що джерело знову закрите.


Які проблеми можуть виникнути, якщо використовувати getResource та перетворити його у файл? Чи можете ви надати посилання?
акауппі

2
За певних обставин - нульовий покажчик: stackoverflow.com/questions/941754/…
Андреас Нойман

Цей код, ймовірно, залишає відкритим обробником для getResourceAsStream.
Сіссо

3
не забудьте closeджерело
Гійом Масме

1
Дякую! Типи байтів не збігаються в розділі Приємніші відгуки про помилки (2.12.x) . А як щодо витоку пам'яті? Чи не слід закривати ресурс?
Альберт Бікеєв

30

Для Scala> = 2,12 використовуйте Source.fromResource:

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

13
Важливо: з Source.fromResourceвами не ставите початковий нахил вперед, який у вас є getResourceAsStream.
vossad01

6
І зауважте, що це 2.12+
rbellamy

а версії 2.10?
Джейдев

12

Рішення Онлінера для 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))

  }

}

введіть тут опис зображення

РЕДАКТУВАННЯ: Кредит оригіналу автора. Повний блог див. Тут


Коли ви копіюєте з веб-сайту, будь ласка, опублікуйте посилання на оригінального автора. Дайте кредит там, де належить. Довідково
ForeverLearner

2

Для Scala 2.11 , якщо getLines не робить саме те, що ви хочете, ви також можете скопіювати файл з банку в локальну файлову систему.

Ось Snippit , який зчитує двійкову Google P12 - формат ключ API з / ресурсів, пише він в / TMP, а потім використовує рядок шляху файлу в якості вхідних даних для свічок Google-таблиць записи .

У світі sbt-native- packger та sbt-зборки , копіювання на локальний файл також корисне при наймасштабніших тестах бінарних файлів. Просто виведіть їх із ресурсів на локальний, запустіть тести та видаліть.

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

До потрібного файлу можна отримати доступ, як показано нижче, з папки ресурсів у масштабі

val file = scala.io.Source.fromFile(s"src/main/resources/app.config").getLines().mkString
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.