Was ist eine einfache und kanonische Methode, um eine ganze Datei in Scala in den Speicher zu lesen? (Idealerweise mit Kontrolle über die Zeichenkodierung.)
Das Beste, was ich mir einfallen lassen kann, ist:
scala.io.Source.fromPath("file.txt").getLines.reduceLeft(_+_)
oder soll ich eine von Javas gottesfürchtigen Redewendungen verwenden , von denen die 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()
Durch das Lesen von Mailinglistendiskussionen ist mir nicht klar, dass scala.io.Source sogar die kanonische E / A-Bibliothek sein soll. Ich verstehe nicht genau, was der beabsichtigte Zweck ist.
... Ich hätte gerne etwas ganz einfaches und leicht zu merkendes. Zum Beispiel ist es in diesen Sprachen sehr schwer, die Redewendung zu vergessen ...
Ruby open("file.txt").read
Ruby File.read("file.txt")
Python open("file.txt").read()
Antworten:
Übrigens ist "
scala.
" nicht wirklich notwendig, da es sowieso immer im Geltungsbereich liegt, und Sie können natürlich den Inhalt von io ganz oder teilweise importieren und vermeiden, "io" voranstellen zu müssen. auch.Das Obige lässt die Datei jedoch offen. Um Probleme zu vermeiden, sollten Sie es folgendermaßen schließen:
Ein weiteres Problem mit dem obigen Code ist, dass er aufgrund seiner Implementierung schrecklich langsam ist. Für größere Dateien sollte man verwenden:
quelle
Um Daniels Lösung zu erweitern, können Sie die Dinge enorm verkürzen, indem Sie den folgenden Import in jede Datei einfügen, die eine Dateimanipulation erfordert:
Damit können Sie jetzt Folgendes tun:
Ich wäre vorsichtig, wenn ich eine ganze Datei in eine einzige lesen würde
String
. Es ist eine sehr schlechte Angewohnheit, die dich früher und härter beißen wird, als du denkst. DiegetLines
Methode gibt einen Wert vom Typ zurückIterator[String]
. Es ist praktisch ein fauler Cursor in die Datei, mit dem Sie genau die Daten untersuchen können, die Sie benötigen, ohne das Risiko einer Speicherüberlastung einzugehen.Oh, und um Ihre implizite Frage zu beantworten
Source
: Ja, es ist die kanonische E / A-Bibliothek. Der meiste Code wirdjava.io
aufgrund seiner untergeordneten Benutzeroberfläche und der besseren Kompatibilität mit vorhandenen Frameworks verwendet. Jeder Code, der eine Auswahl hat, sollte jedoch verwendet werdenSource
, insbesondere für die einfache Dateimanipulation.quelle
quelle
(EDIT: Dies funktioniert nicht in Scala 2.9 und vielleicht auch nicht in 2.8)
Kofferraum verwenden:
quelle
slurp
"? Haben wir den offensichtlichen, intuitiven Namen wirklich fallen lassen? Das Problem dabeislurp
ist, dass es für jemanden mit Englisch als Muttersprache im Nachhinein vielleicht Sinn macht, aber man würde nie daran denken!File
ist nicht mehr in 2.8.0, nicht wahr?slurp
ist fantastisch! :) Es war fantastisch? Ich finde es nicht ; (Kontrolle über die Zeichenkodierung und keine zu bereinigenden Ressourcen. Möglicherweise auch optimiert (z. B.
Files.readAllBytes
Zuweisen eines der Dateigröße entsprechenden Byte-Arrays).quelle
Mir wurde gesagt, dass Source.fromFile problematisch ist. Persönlich hatte ich 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
quelle
Mit getLines () in scala.io.Source wird verworfen, welche Zeichen für Zeilenabschlusszeichen verwendet wurden (\ n, \ r, \ r \ n usw.).
Das Folgende sollte es Zeichen für Zeichen beibehalten und keine übermäßige Verkettung von Zeichenfolgen (Leistungsprobleme) verursachen:
quelle
Noch eine: 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:
Sie können auch Ihren eigenen Codec für alles bereitstellen, was ein Lese- / Schreibvorgang ausführt (dies setzt scala.io.Codec.default voraus, wenn Sie keinen angeben):
quelle
Genau wie in Java mit der CommonsIO-Bibliothek:
Auch viele Antworten hier vergessen Charset. Es ist besser, es immer explizit anzugeben, sonst wird es eines Tages getroffen.
quelle
Berücksichtigen Sie diese implizite Klasse (Scala 2.10 und höher), um die Ruby-Syntax (und die Semantik) des Öffnens und Lesens einer Datei zu emulieren.
Auf diese Weise,
quelle
Wie einige Leute bereits erwähnt haben, ist scala.io.Source aufgrund von Verbindungslecks am besten zu vermeiden.
Wahrscheinlich sind Scalax und reine Java-Bibliotheken wie Commons-Io die besten Optionen, bis das neue Inkubator-Projekt (dh Scala-Io) zusammengeführt wird.
quelle
Sie können auch Path from scala io verwenden, um Dateien zu lesen und zu verarbeiten.
Jetzt können Sie den Dateipfad folgendermaßen abrufen: -
Sie können auch Terminatoren einschließen, diese sind jedoch standardmäßig auf false gesetzt.
quelle
Um das Lesen / Hochladen einer (großen) Datei insgesamt zu beschleunigen, sollten Sie die Größe von
bufferSize
(Source.DefaultBufSize
auf2048
) setzen, z. B. wie folgt:Hinweis Source.scala . Weitere Informationen finden Sie unter Scala Fast-Textdatei lesen und in den Speicher hochladen .
quelle
Sie müssen nicht jede einzelne Zeile analysieren und dann erneut verketten ...
Ich benutze das lieber:
quelle
val content = source.mkString
Codec
. Ich habe einensbt test
Testfehler erhalten, weil ich ihn nicht einstellen kann, während der Testbefehl von Intellij alle Tests besteht. Und Sie können verwendendef using
von dieserWenn Ihnen eine Abhängigkeit von Drittanbietern nichts ausmacht, sollten Sie meine OS-Lib-Bibliothek verwenden . Dies macht das Lesen / Schreiben von Dateien und das Arbeiten mit dem Dateisystem sehr bequem:
mit einzeiligen Helfern zum Lesen von Bytes , Lesen von Chunks , Lesen von Zeilen und vielen anderen nützlichen / allgemeinen Operationen
quelle
Die offensichtliche Frage lautet: "Warum möchten Sie die gesamte Datei einlesen?" Dies ist offensichtlich keine skalierbare Lösung, wenn Ihre Dateien sehr groß werden. Das
scala.io.Source
gibt Ihnen eineIterator[String]
von dergetLines
Methode zurück, die sehr nützlich und prägnant ist.Es ist keine große Aufgabe, eine implizite Konvertierung mit den zugrunde liegenden Java-E / A-Dienstprogrammen zu erstellen, um a
File
, aReader
oder aInputStream
in a zu konvertierenString
. Ich denke, dass die mangelnde Skalierbarkeit bedeutet, dass sie richtig sind, dies nicht zur Standard-API hinzuzufügen.quelle
Drucken Sie jede Zeile aus, wie z. B. Java BufferedReader, lesen Sie jede Zeile und drucken Sie sie aus:
Äquivalent:
quelle
In Argumenten können Sie einen Dateipfad angeben, der alle Zeilen zurückgibt
quelle