如何写入Kotlin中的文件?

时间:2016-02-16 22:29:01

标签: kotlin file-writing

我似乎还没有找到这个问题,但是打开/创建文件,写入文件然后关闭它的最简单,最常用的方法是什么?查看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方式吗?

7 个答案:

答案 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的内容,使它们成为你想要的样子。

另外一个答案是https://stackoverflow.com/a/35462184/3679676

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