如何在Kotlin中写入文件?

我似乎还没有找到这个问题,但打开/创建文件,写入文件,然后关闭它的最简单,最习惯的方法是什么? 看看kotlin.io参考和Java文档,我设法得到这个:

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() } 

这是有效的,但我想知道是否有一个“适当的”科特林这样做的方式?

有点更习惯 对于PrintWriter,这个例子:

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

for循环或forEach取决于你的风格。 没有理由使用append(x)因为这基本上是write(x.toString()) ,你已经给它一个字符串。 而println(x)基本上在将null转换为"null"之后write(x) 。 和println()做正确的行结束。

如果您正在使用Kotlin的data类,则已经可以输出它们了,因为它们已经有了一个很好的toString()方法。

另外,在这种情况下,如果你想使用BufferedWriter它会产生相同的结果:

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

你也可以使用out.newLine()而不是\n如果你想让它正确的运行它的当前操作系统。 如果你一直这么做,你可能会创建一个扩展函数:

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

然后用它来代替:

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

这就是科特林如何滚动。 改变API中的东西,使他们成为你想要的东西。

对此的狂野不同的味道在另一个答案: https : //stackoverflow.com/a/35462184/3679676

其他有趣的变化,所以你可以看到Kotlin的力量:

一个快速的版本,通过创建字符串一次写入所有:

 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")) 

或者假设你可以做其他功能性的东西,比如过滤器行,或者只取前100行等。你可以走这条路:

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

或者给定一个Iterable ,允许通过创建扩展函数(类似于上面的writeText()版本,但是对内容进行流式处理,而不是首先实现一个大字符串) 来将其写入文件。

 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) } 

用作以下任何一种:

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

或在每个项目上使用默认的toString():

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

或者给定一个File ,允许通过创建这个扩展函数来从Iterable填充它

 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() } } } 

使用:

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

或在每个项目上使用默认的toString():

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

如果你已经有其他的toFile扩展名,你可以重写一个扩展名:

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

它对我来说大体上看起来不错。 唯一不同的是我使用ReadWrite中定义的“ use ”扩展来自动关闭写入器。

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

一些Kotlin魔术允许在每个读或写通话中省略引用流:

 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) } } 
Interesting Posts