Jak czytać pliki z folderu zasobów w Scali?

112

Mam strukturę folderów jak poniżej:

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

iw tych folderach mam swoje pliki, które muszę przeczytać. Oto kod:

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
źródło
dlaczego odpowiedź udzielona przez Andreasa Neumanna nie została przyjęta, jeśli masz jakieś dodatkowe pytanie, skomentuj je. -1.
Vishrant,

Odpowiedzi:

201

Zasoby w Scali działają dokładnie tak samo, jak w Javie. Najlepiej postępować zgodnie z najlepszymi praktykami Java i umieszczać wszystkie zasoby w src/main/resourcesi src/test/resources.

Przykładowa struktura folderów:

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

Scala 2.12.x && 2.13.x odczytuje zasób

Aby odczytać zasoby, obiekt Source udostępnia metodę fromResource .

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

czytanie zasobów przed 2.12 (nadal moje ulubione ze względu na zgodność z jarami)

Aby odczytać zasoby, możesz użyć getClass.getResource i getClass.getResourceAsStream .

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

ładniejsza informacja o błędach (2.12.x && 2.13.x)

Aby uniknąć niemożliwych do usunięcia błędów NPE Java, rozważ:

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

dobrze wiedzieć

Należy pamiętać, że getResourceAsStream działa również dobrze, gdy zasoby są częścią jar , getResource , który zwraca adres URL, który jest często używany do tworzenia pliku, może prowadzić do problemów.

w produkcji

W kodzie produkcyjnym proponuję upewnić się, że źródło jest ponownie zamknięte.

Andreas Neumann
źródło
Jakie problemy mogą wystąpić, jeśli użyjesz getResource i przekształcisz go w plik? Czy możesz podać link?
akauppi
2
W niektórych przypadkach pusty Pointer: stackoverflow.com/questions/941754/…
Andreas Neumann
Ten kod prawdopodobnie pozostawia otwartą procedurę obsługi dla getResourceAsStream.
Sisso,
3
nie zapomnij o closeŹródle
Guillaume Massé
1
Dzięki! Typy bajtów nie pasują do sekcji Ładniejsze informacje o błędach (2.12.x) . A co z wyciekami pamięci? Czy zasób nie powinien być zamknięty?
Albert Bikeev
30

Dla Scala> = 2.12 użyj Source.fromResource:

scala.io.Source.fromResource("located_in_resouces.any")
Mohsen Kashi
źródło
13
Ważne: z Source.fromResourcetobą nie umieszczaj początkowego ukośnika, który masz getResourceAsStream.
vossad01
6
I zwróć uwagę, że to jest 2.12+
rbellamy
a co z wersjami 2.10?
Jaydev,
12

Rozwiązanie onliner dla Scala> = 2.12

val source_html = Source.fromResource("file.html").mkString
freedev
źródło
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))

  }

}

wprowadź opis obrazu tutaj

EDYCJA: Kredyt dla pierwotnego autora. Zapoznaj się z pełnym blogiem tutaj

Sri
źródło
Kiedy kopiujesz ze strony internetowej, umieść link do oryginalnego autora. Udziel kredytu tam, gdzie jest on należny. Patrz: fruzenshtein.com/scala-working-with-resources-folders-files
ForeverLearner
2

Dla Scali 2.11 , jeśli getLines nie robi dokładnie tego, co chcesz, możesz również skopiować plik a z jar do lokalnego systemu plików.

Oto fragment, który odczytuje binarny klucz API w formacie google .p12 z / resources, zapisuje go w / tmp, a następnie używa ciągu ścieżki pliku jako danych wejściowych do zapisu w arkuszu kalkulacyjnym spark-google-spreadsheets .

W świecie sbt-native-packager i sbt-assembly , kopiowanie do lokalnego jest również przydatne przy testach plików binarnych o największej skali. Po prostu wyrzuć je z zasobów do lokalnego, uruchom testy, a następnie usuń.

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
źródło
2

Dostęp do wymaganego pliku można uzyskać jak poniżej z folderu zasobów w scali

val file = scala.io.Source.fromFile(s"src/main/resources/app.config").getLines().mkString
Dileep Dominic
źródło