wake-up-neo.com

Scala: Schreibe einen String in eine Datei in einer Anweisung

Zum Lesen von Dateien in Scala gibt es

Source.fromFile("file.txt").mkString

Gibt es eine äquivalente und präzise Möglichkeit, eine Zeichenfolge in eine Datei zu schreiben?

Die meisten Sprachen unterstützen so etwas. Mein Favorit ist Groovy:

def f = new File("file.txt")
// Read
def s = f.text
// Write
f.text = "file contents"

Ich möchte den Code für Programme verwenden, die von einer einzelnen Zeile bis zu einer kurzen Codeseite reichen. Die Nutzung einer eigenen Bibliothek ist hier nicht sinnvoll. Ich erwarte von einer modernen Sprache, dass ich bequem etwas in eine Datei schreiben kann.

Es gibt ähnliche Posts, die jedoch nicht meine genaue Frage beantworten oder sich auf ältere Scala Versionen konzentrieren.

Beispielsweise:

134
smartnut007

Eine kurze Zeile:

import Java.io.PrintWriter
new PrintWriter("filename") { write("file contents"); close }
68
LRLucena

Es ist seltsam, dass niemand NIO.2-Operationen vorgeschlagen hatte (verfügbar seit Java 7):

import Java.nio.file.{Paths, Files}
import Java.nio.charset.StandardCharsets

Files.write(Paths.get("file.txt"), "file contents".getBytes(StandardCharsets.UTF_8))

Ich denke, dies ist bei weitem der einfachste, einfachste und idiomatischste Weg, und es sind keine Abhängigkeiten ohne Java selbst erforderlich.

152

Hier ist ein kompakter Einzeiler, der reflect.io.file verwendet. Dies funktioniert mit Scala 2.12:

reflect.io.File("filename").writeAll("hello world")

Wenn Sie alternativ die Bibliotheken Java verwenden möchten, können Sie diesen Hack ausführen:

Some(new PrintWriter("filename")).foreach{p => p.write("hello world"); p.close}
80
Garrett Hall

Wenn Sie die Groovy-Syntax mögen, können Sie das Entwurfsmuster Pimp-My-Library für Scala verwenden:

import Java.io._
import scala.io._

class RichFile( file: File ) {

  def text = Source.fromFile( file )(Codec.UTF8).mkString

  def text_=( s: String ) {
    val out = new PrintWriter( file , "UTF-8")
    try{ out.print( s ) }
    finally{ out.close }
  }
}

object RichFile {

  implicit def enrichFile( file: File ) = new RichFile( file )

}

Es wird wie erwartet funktionieren:

scala> import RichFile.enrichFile
import RichFile.enrichFile

scala> val f = new File("/tmp/example.txt")
f: Java.io.File = /tmp/example.txt

scala> f.text = "hello world"

scala> f.text
res1: String = 
"hello world
40
paradigmatic
import sys.process._
"echo hello world" #> new Java.io.File("/tmp/example.txt") !
22
xiefei

Sie können einfach Apache File Utils verwenden. Schauen Sie sich die Funktion writeStringToFile an. Wir verwenden diese Bibliothek in unseren Projekten.

12
RyuuGan

Eine Mikrobibliothek, die ich geschrieben habe: https://github.com/pathikrit/better-files

file.write("Hi!")

oder

file << "Hi!"
12
pathikrit

Das ist prägnant genug, denke ich:

scala> import Java.io._
import Java.io._

scala> val w = new BufferedWriter(new FileWriter("output.txt"))
w: Java.io.BufferedWriter = [email protected]

scala> w.write("Alice\r\nBob\r\nCharlie\r\n")

scala> w.close()
7
Luigi Sgro

Man hat auch dieses Format, das sowohl prägnant als auch die zugrunde liegende Bibliothek schön geschrieben ist (siehe den Quellcode):

import scalax.io.Codec
import scalax.io.JavaConverters._

implicit val codec = Codec.UTF8

new Java.io.File("hi-file.txt").asOutput.write("I'm a hi file! ... Really!")
6
Dibbeke

Ich weiß, es ist keine einzige Zeile, aber sie löst die Sicherheitsprobleme, soweit ich das beurteilen kann.

// This possibly creates a FileWriter, but maybe not
val writer = Try(new FileWriter(new File("filename")))
// If it did, we use it to write the data and return it again
// If it didn't we skip the map and print the exception and return the original, just in-case it was actually .write() that failed
// Then we close the file
writer.map(w => {w.write("data"); w}).recoverWith{case e => {e.printStackTrace(); writer}}.map(_.close)

Wenn Sie sich nicht um die Ausnahmebehandlung gekümmert haben, können Sie schreiben

writer.map(w => {w.writer("data"); w}).recoverWith{case _ => writer}.map(_.close)
2
J_mie6

Sie können dies mit einer Mischung aus Java und Scala) - Bibliotheken tun. Sie haben die volle Kontrolle über die Zeichenkodierung. Leider werden die Datei-Handles nicht richtig geschlossen.

scala> import Java.io.ByteArrayInputStream
import Java.io.ByteArrayInputStream

scala> import Java.io.FileOutputStream
import Java.io.FileOutputStream

scala> BasicIO.transferFully(new ByteArrayInputStream("test".getBytes("UTF-8")), new FileOutputStream("test.txt"))
2

UPDATE: Ich habe seitdem eine effektivere Lösung erstellt, auf die ich hier näher eingegangen bin: https://stackoverflow.com/a/34277491/50111

Ich stelle fest, dass ich immer mehr im Arbeitsblatt Scala in Scala IDE für Eclipse arbeite (und ich glaube, dass es in IntelliJ IDEA etwas Äquivalentes gibt). Wie auch immer, ich muss in der Lage sein, einen Einzeiler zu erstellen, um einen Teil des Inhalts auszugeben, wenn die Meldung "Ausgabe überschreitet Grenzwert" angezeigt wird. Nachricht, wenn ich etwas Wichtiges tue, besonders mit den Scala Sammlungen.

Ich habe mir einen Einzeiler ausgedacht, den ich oben in jedes neue Scala Arbeitsblatt eingefügt habe, um dies zu vereinfachen (und daher muss ich nicht die gesamte Übung zum Importieren externer Bibliotheken ausführen, um eine sehr einfache Anforderung zu erfüllen). Wenn Sie ein Stickler sind und feststellen, dass es sich technisch gesehen um zwei Zeilen handelt, dient dies nur dazu, die Lesbarkeit in diesem Forum zu verbessern. Es ist eine einzelne Zeile in meinem Arbeitsblatt Scala.

def printToFile(content: String, location: String = "C:/Users/jtdoe/Desktop/WorkSheet.txt") =
  Some(new Java.io.PrintWriter(location)).foreach{f => try{f.write(content)}finally{f.close}}

Und die Verwendung ist einfach:

printToFile("A fancy test string\ncontaining newlines\nOMG!\n")

Auf diese Weise kann ich optional den Dateinamen angeben, falls ich über den Standard hinaus zusätzliche Dateien haben möchte (wodurch die Datei bei jedem Aufruf der Methode vollständig überschrieben wird).

Die zweite Verwendung ist also einfach:

printToFile("A fancy test string\ncontaining newlines\nOMG!\n", "C:/Users/jtdoe/Desktop/WorkSheet.txt")

Genießen!

1

Durch die Magie des Semikolons können Sie alles, was Sie mögen, zu einem Einzeiler machen.

import Java.io.PrintWriter
import Java.nio.file.Files
import Java.nio.file.Paths
import Java.nio.charset.StandardCharsets
import Java.nio.file.StandardOpenOption
val outfile = Java.io.File.createTempFile("", "").getPath
val outstream = new PrintWriter(Files.newBufferedWriter(Paths.get(outfile)
  , StandardCharsets.UTF_8
  , StandardOpenOption.WRITE)); outstream.println("content"); outstream.flush(); outstream.close()
0
Ion Freeman