我似乎还没有找到这个问题,但是打开/创建文件,写入文件然后关闭它的最简单,最常用的方法是什么?查看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()
}
这有效,但我想知道是否有一种“适当的”Kotlin方式吗?
答案 0 :(得分:82)
有点习惯。对于PrintWriter,此示例:
File("somefile.txt").printWriter().use { out ->
history.forEach {
out.println("${it.key}, ${it.value}")
}
}
for
循环或forEach
取决于您的风格。没有理由使用append(x)
,因为那基本上是write(x.toString())
,你已经给它一个字符串了。将println(x)
转换为write(x)
后null
基本上"null"
。 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}")
}
}
这就是Kotlin的表现。改变API的内容,使它们成为你想要的样子。
答案 1 :(得分:22)
其他有趣的变化让您可以看到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)
}
答案 2 :(得分:5)
它对我来说看起来很好。我唯一不同的是使用ReadWrite中定义的“http://www.mywebsite.com/test?author=sam&test=3”扩展来自动关闭编写器。
PrintWriter("file.txt").use {
for ((member, originalInput) in history) { // history: Map<Member, String>
it.append("$member, $originalInput\n")
}
}
答案 3 :(得分:1)
某些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)
}
}
答案 4 :(得分:1)
您至少可以使用:
FileWriter(filename).use { it.write(text) }
FileWriter是用于编写字符文件的便捷类(由Java提供,因此在Kotlin中可用)。它扩展了Closeable,因此可以被Kotlin的“ .use”扩展方法使用。
扩展块后,.use扩展方法会自动关闭调用对象,从而提供了一种惯用的方式来在文件写入后关闭文件。
答案 5 :(得分:0)
try{
val fileWriter = FileWriter("test.txt", true)
fileWriter.write(string+ "\n")
fileWriter.close()
} catch (exception: Exception){
println(exception.message)
}
答案 6 :(得分:0)
示例简单
val path = context!!.filesDir.absolutePath // => /data/user/0/com.example.test/files
File("$path/filename.txt").writeText("hello")