2

Alternative title: how does one "nicely" "update" the contents of text files with Kotlin?

I have seen how do i write to a file in kotlin.

Basically, the suggested solution there is based on creating a File object, to then write to it: File("somefile.txt").printWriter().use ...

But well: I already have code like this:

File(fname).bufferedReader().lineSequence().flatMap { transform(it) }

where transform() is my own method that either returns the original line, or some updates lines when some specific match matched. (its signature is transform(line : String) : Sequence<String>)

Sure: I could assign the result of flatMap() to some temporary variable, to then use that with printWriter().use.

But is there a nice, canonical way that works without a temporary variable?

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Just use it directly. Nothing requires the declaration of a variable to use it elsewhere. `[...].printWriter().use { File(fname).bufferedReader().lineSequence().flatMap { transform(it) } }` – Zoe Sep 17 '18 at 14:53
  • 2
    @Zoe Feel free to put that into an answer. Would be easier to read, and earn you an upvote + accept. – GhostCat Sep 17 '18 at 14:53
  • joinToString() and File.writeText? – m0skit0 Sep 17 '18 at 14:54
  • The code i posted in the comment is wrong. The return type doesn't match, and it doesn't actually write anything. Anyways, what does transform return? – Zoe Sep 17 '18 at 15:03

1 Answers1

2

Note that your reading code (File().bufferedReader().lineSequence()) can already be simplified to:

File(fname).useLines {
  it.flatMap(::transform)
}

Now regarding writing without putting it in an intermediate variable...

File("writeTo").bufferedWriter().use { writer ->
  File("readFrom").useLines { lines ->
    lines.flatMap(::transform)
         .forEach { 
           writer.appendln(it)
         }
  }
}

But I am not yet really convinced about it... I don't really like it ;-) I rather like something like:

File("readFrom").useLines {
   ..
}.writeTo("writeTo")

but that is not going to work as long as I use useLines ;-)

But here is something similar:

File("readFrom").useLines {
  it.flatMap(::transform)
    .writeTo(File("writeTo"))
}

But this requires the following extension function then:

fun Sequence<String>.writeTo(file: File) {
  file.bufferedWriter().use { writer -> forEach { writer.appendln(it) } }
}

On the other hand... I always wanted to have a sequence.toFile-writer ;-) adapted it already to use a delimiter as parameter...

Roland
  • 22,259
  • 4
  • 57
  • 84