2016-02-16 18 views
27

Ich kann diese Frage nicht scheinen noch zu finden, aber was ist die einfachste, idiomatischen Weise Öffnen/Erstellen einer Datei, um es zu schreiben, und schließen Sie es dann? Mit Blick auf die kotlin.io Referenz und der Java-Dokumentation ich es geschafft, dies zu erhalten:Wie schreibe ich in eine Datei in Kotlin?

fun write() { 
    val writer = PrintWriter("file.txt") // java.io.PrintWriter 

    for ((member, originalInput) in history) { // history: Map<Member, String> 
     writer.append("$member, $originalInput\n") 
    } 

    writer.close() 
} 

Dies funktioniert, aber ich frage mich, ob es eine „richtige“ Kotlin war Art und Weise, dies zu tun?

+2

ich habe mehr Variationen in einer neuen Antwort für Spaß, Ihnen mehr Ideen der Dinge zu geben, die Sie tun können. –

Antwort

49

Ein bisschen mehr idiomatisch. Für Printwriter, dieses Beispiel:

File("somefile.txt").printWriter().use { out -> 
    history.forEach { 
     out.println("${it.key}, ${it.value}") 
    } 
} 

Die for Schleife oder forEach hängt von Ihrem Stil. Kein Grund append(x) zu verwenden, da die im Grunde write(x.toString()) ist und Sie es bereits eine Zeichenfolge geben. Und println(x) tut im Grunde write(x) nach einem null zu "null" konvertieren. Und println() macht die richtige Zeilenendung. Wenn Sie data Klassen von Kotlin verwenden, können sie bereits ausgegeben werden, da sie bereits eine schöne toString() Methode haben.

Auch in diesem Fall, wenn man will BufferedWriter verwenden, es würde die gleichen Ergebnisse produzieren:

File("somefile.txt").bufferedWriter().use { out -> 
    history.forEach { 
     out.write("${it.key}, ${it.value}\n") 
    } 
} 

Sie können auch out.newLine() statt \n verwenden, wenn Sie es für das aktuelle Betriebssystem korrekt sein wollen was es läuft. Und wenn man die ganze Zeit tun, würden Sie wahrscheinlich eine Erweiterungsfunktion erstellen:

fun BufferedWriter.writeLn(line: String) { 
    this.write(line) 
    this.newLine() 
} 

und dann verwenden, statt:

File("somefile.txt").bufferedWriter().use { out -> 
    history.forEach { 
     out.writeLn("${it.key}, ${it.value}") 
    } 
} 

Und das ist, wie Kotlin Rollen. Ändere die Dinge in den APIs, um sie so zu gestalten, wie sie sein sollen.

völlig unterschiedliche Aromen hierfür sind in einer anderen Antwort: https://stackoverflow.com/a/35462184/3679676

+1

Dank für dieses und die anderen mehr „Spaß“ Variationen! +1 – yiwei

+1

es kann eine andere mögliche Lösung: Datei (Dateiname) .writeText (Iterable .joinToString(), Charsets.UTF_8) –

+0

@IstvanNagy abhängig von der Größe des iterablen und wenn Sie die vollständige Zeichenfolge vor dem Schreiben materialisieren möchten. Ich werde es auf die alternative Antwort hinzufügen, es ist schön kurz! –

5

Es sieht meistens ok für mich. Das einzige, was anders ich tun würde, ist die „use“ -Erweiterung in Lese-Schreib den Schreiber nahe an Auto definiert verwenden.

PrintWriter("file.txt").use { 
    for ((member, originalInput) in history) { // history: Map<Member, String> 
    it.append("$member, $originalInput\n") 
    }  
} 
15

Andere Spaß Variationen so können Sie die Leistung von Kotlin sehen:

Eine schnelle Version, indem Sie die Zeichenfolge zu schaffen alles auf einmal zu schreiben:

File("somefile.txt").writeText(history.entries.joinToString("\n") { "${it.key}, ${it.value}" }) 
// or just use the toString() method without transform: 
File("somefile.txt").writeText(x.entries.joinToString("\n")) 

oder vorausgesetzt, Sie tun könnten andere funktionelle Dinge wie Filterlinien oder nehmen Sie nur die erste 100 usw.Man könnte diesen Weg gehen:

File("somefile.txt").printWriter().use { out -> 
    history.map { "${it.key}, ${it.value}" } 
      .filter { ... } 
      .take(100) 
      .forEach { out.println(it) } 
} 

Oder ein Iterable gegeben, damit sie in eine Datei schreiben unter Verwendung eines in einen String umwandeln, durch Erweiterungsfunktionen Erstellen von (ähnlich writeText() Version oben, aber strömt den Inhalt statt eine große Reihe zuerst) materialisiert:

fun <T: Any> Iterable<T>.toFile(output: File, transform: (T)->String = {it.toString()}) { 
    output.bufferedWriter().use { out -> 
     this.map(transform).forEach { out.write(it); out.newLine() } 
    } 
} 

fun <T: Any> Iterable<T>.toFile(outputFilename: String, transform: (T)->String = {it.toString()}) { 
    this.toFile(File(outputFilename), transform) 
} 

wie jeder von diesen verwendet:

history.entries.toFile(File("somefile.txt")) { "${it.key}, ${it.value}" } 

history.entries.toFile("somefile.txt") { "${it.key}, ${it.value}" } 

oder Standard toString() für jedes Element:

history.entries.toFile(File("somefile.txt")) 

history.entries.toFile("somefile.txt") 

oder ein File gegeben, damit sie von einem Iterable, indem diese Erweiterung Füllfunktion:

fun <T: Any> File.fillWith(things: Iterable<T>, transform: (T)->String = {it.toString()}) { 
    this.bufferedWriter().use { out -> 
     things.map(transform).forEach { out.write(it); out.newLine() } 
    } 
} 

mit Verwendung von:

File("somefile.txt").fillWith(history.entries) { "${it.key}, ${it.value}" } 

oder Standard toString() für jedes Element:

File("somefile.txt").fillWith(history.entries) 

, die, wenn Sie die anderen toFile Erweiterung bereits hatte, konnte man umschreiben eine Nebenstelle anrufen, die die anderen:

fun <T: Any> File.fillWith(things: Iterable<T>, transform: (T)->String = {it.toString()}) { 
    things.toFile(this, transform) 
} 
+0

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-file/write-text.html –

0

Einige Kotlin Magie Referenzierung der Strom auf jeder wegzulassen erlaubt rufen lesen oder schreiben:

fun <T : Closeable, R> T.useWith(block: T.() -> R): R = use { with(it, block) } 

File("a.in").bufferedReader().useWith { 
    File("a.out").printWriter().useWith { 
     val (a, b) = readLine()!!.split(' ').map(String::toInt) 
     println(a + b) 
    } 
} 

Scanner(File("b.in")).useWith { 
    PrintWriter("b.out").useWith { 
     val a = nextInt() 
     val b = nextInt() 
     println(a + b) 
    } 
} 
Verwandte Themen