Как читать файлы из папки ресурсов в 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.
Vishrant 05

Ответы:

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, примите во внимание:

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 также отлично работает, когда ресурсы являются частью jar- файла , getResource , который возвращает URL-адрес, который часто используется для создания файла, может привести к проблемам там.

в производстве

В производственном коде я предлагаю убедиться, что исходный код снова закрыт.

Андреас Нойманн
источник
Какие проблемы могут возникнуть при использовании getResource и преобразовании его в файл? Можете дать ссылку?
akauppi
2
В некоторых случаях в качестве нулевого указателя: stackoverflow.com/questions/941754/…
Андреас Нойманн,
Этот код, вероятно, оставляет открытым обработчик для getResourceAsStream.
Sisso
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?
Jaydev
12

Онлайн-решение для Scala> = 2.12

val source_html = Source.fromResource("file.html").mkString
Freedev
источник
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 не делает именно то, что вы хотите, вы также можете скопировать файл из jar в локальную файловую систему.

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

В мире sbt-native- packager и sbt-assembly копирование на локальное также полезно с тестами масштабных двоичных файлов. Просто вытолкните их из ресурсов на локальные, запустите тесты, а затем удалите.

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

Доступ к требуемому файлу можно получить, как показано ниже, из папки ресурсов в scala.

val file = scala.io.Source.fromFile(s"src/main/resources/app.config").getLines().mkString
Дилип Доминик
источник