read - scala textfile




Lesen Sie die gesamte Datei in Scala? (12)

(EDIT: Das funktioniert nicht in Scala 2.9 und vielleicht auch nicht in 2.8)

Verwenden Sie Stamm:

scala> io.File("/etc/passwd").slurp
res0: String = 
##
# User Database
# 
... etc

Was ist eine einfache und kanonische Art, eine ganze Datei in Scala zu speichern? (Idealerweise mit Kontrolle über Zeichencodierung.)

Das Beste, was ich mir vorstellen kann, ist:

scala.io.Source.fromPath("file.txt").getLines.reduceLeft(_+_)

oder soll ich eines der gottverdammten Idiome von Java benutzen, von denen das beste (ohne Verwendung einer externen Bibliothek) zu sein scheint:

import java.util.Scanner
import java.io.File
new Scanner(new File("file.txt")).useDelimiter("\\Z").next()

Beim Lesen von Mailinglisten-Diskussionen ist mir nicht klar, dass scala.io.Source sogar die kanonische E / A-Bibliothek sein soll. Ich verstehe nicht genau, was der beabsichtigte Zweck genau ist.

... Ich möchte etwas totes - einfach und leicht zu merken. Zum Beispiel ist es in diesen Sprachen sehr schwierig, das Idiom zu vergessen ...

Ruby    open("file.txt").read
Ruby    File.read("file.txt")
Python  open("file.txt").read()

Die Verwendung von getLines () in scala.io.Source verwirft, welche Zeichen für Zeilenabschlusszeichen verwendet wurden (\ n, \ r, \ r \ n usw.)

Das folgende sollte es Zeichen für Zeichen beibehalten und führt keine übermäßige Zeichenfolge-Verkettung (Leistungsprobleme):

def fileToString(file: File, encoding: String) = {
  val inStream = new FileInputStream(file)
  val outStream = new ByteArrayOutputStream
  try {
    var reading = true
    while ( reading ) {
      inStream.read() match {
        case -1 => reading = false
        case c => outStream.write(c)
      }
    }
    outStream.flush()
  }
  finally {
    inStream.close()
  }
  new String(outStream.toByteArray(), encoding)
}

Drucken Sie jede Zeile, verwenden Sie Java BufferedReader, lesen Sie die Zeile und drucken Sie sie aus:

scala.io.Source.fromFile("test.txt" ).foreach{  print  }

gleichwertig:

scala.io.Source.fromFile("test.txt" ).foreach( x => print(x))

Eine mehr: https://github.com/pathikrit/better-files#streams-and-codecs

Verschiedene Möglichkeiten, eine Datei zu schlürfen, ohne den Inhalt in den Speicher zu laden:

val bytes  : Iterator[Byte]            = file.bytes
val chars  : Iterator[Char]            = file.chars
val lines  : Iterator[String]          = file.lines
val source : scala.io.BufferedSource   = file.content 

Sie können auch Ihren eigenen Codec für alles bereitstellen, das Lesen / Schreiben durchführt (es nimmt scala.io.Codec.default an, wenn Sie keinen bereitstellen):

val content: String = file.contentAsString  // default codec
// custom codec:
import scala.io.Codec
file.contentAsString(Codec.ISO8859)
//or
import scala.io.Codec.string2codec
file.write("hello world")(codec = "US-ASCII")

Mir wurde gesagt, dass Source.fromFile problematisch ist. Ich persönlich hatte Probleme beim Öffnen großer Dateien mit Source.fromFile und musste auf Java InputStreams zurückgreifen.

Eine weitere interessante Lösung ist die Verwendung von Scalax. Hier ist ein Beispiel für einen gut kommentierten Code, der eine Protokolldatei mit ManagedResource öffnet, um eine Datei mit scalax-Helfern zu öffnen: http://pastie.org/pastes/420714


Sie können auch Path from scala io verwenden, um Dateien zu lesen und zu verarbeiten.

import scalax.file.Path

Jetzt können Sie Dateipfad mit diesem erhalten: -

val filePath = Path("path_of_file_to_b_read", '/')
val lines = file.lines(includeTerminator = true)

Sie können Terminatoren auch einschließen, aber standardmäßig ist es auf false gesetzt.


Um Daniels Lösung zu erweitern, können Sie die Dinge erheblich verkürzen, indem Sie den folgenden Import in jede Datei einfügen, die Dateimanipulation erfordert:

import scala.io.Source._

Damit können Sie jetzt Folgendes tun:

val lines = fromFile("file.txt").getLines

Ich würde vorsichtig sein, eine ganze Datei in einen einzigen String lesen. Es ist eine sehr schlechte Angewohnheit, die dich früher und härter beißen wird, als du denkst. Die getLines Methode gibt einen Wert vom Typ Iterator[String] . Es ist effektiv ein fauler Cursor in die Datei, so dass Sie nur die Daten untersuchen können, die Sie benötigen, ohne die Speicherüberflutung zu riskieren.

Oh, und um deine implizite Frage nach Source zu beantworten: Ja, es ist die kanonische E / A-Bibliothek. Der meiste Code endet mit java.io aufgrund seiner untergeordneten Schnittstelle und einer besseren Kompatibilität mit bestehenden Frameworks, aber jeder Code, der eine Wahl hat, sollte Source , insbesondere für einfache Dateimanipulation.


Um die Ruby-Syntax zu emulieren (und die Semantik zu vermitteln), eine Datei zu öffnen und zu lesen, betrachte diese implizite Klasse (Scala 2.10 und höher),

import java.io.File

def open(filename: String) = new File(filename)

implicit class RichFile(val file: File) extends AnyVal {
  def read = io.Source.fromFile(file).getLines.mkString("\n")
}

Auf diese Weise,

open("file.txt").read

wie einige Leute erwähnt scala.io.Source ist am besten wegen Verbindungslecks vermieden werden.

Wahrscheinlich sind scalax und pure java libs wie commons-io die besten Optionen, bis das neue Inkubator-Projekt (dh scala-io) zusammengeführt wird.


// for file with utf-8 encoding
val lines = scala.io.Source.fromFile("file.txt", "utf-8").getLines.mkString

import scala.io.source
object ReadLine{
def main(args:Array[String]){
if (args.length>0){
for (line <- Source.fromLine(args(0)).getLine())
println(line)
}
}

In Argumenten können Sie den Dateipfad angeben und es werden alle Zeilen zurückgegeben


val lines = scala.io.Source.fromFile("file.txt").mkString

Übrigens ist " scala. " Nicht wirklich notwendig, da es sowieso immer im Umfang ist, und Sie können natürlich den Inhalt von io ganz oder teilweise importieren und vermeiden, "io" voranzustellen. auch.

Das oben genannte lässt jedoch die Datei geöffnet. Um Probleme zu vermeiden, sollten Sie es wie folgt schließen:

val source = scala.io.Source.fromFile("file.txt")
val lines = try source.mkString finally source.close()

Ein weiteres Problem mit dem obigen Code ist, dass es aufgrund seiner Implementierungscharakter schrecklich langsam ist. Für größere Dateien sollte man verwenden:

source.getLines mkString "\n"




scala