如何在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) } }