web-dev-qa-db-ja.com

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

これは機能しますが、これを行うための「適切な」コトリンの方法があるかどうか疑問に思っていましたか?

44
yiwei

もう少し慣用的です。 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クラスを使用している場合、既にNice toString()メソッドがあるため、すでに出力できます。

また、この場合、BufferedWriterを使用する場合、同じ結果が生成されます。

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

また、\nの代わりにout.newLine()を使用して、それが実行されている現在のオペレーティングシステムに対して正しいものにすることもできます。そして、あなたがいつもそうしているなら、おそらく拡張機能を作成するでしょう:

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

86
Jayson Minard

その他の楽しいバリエーションので、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)
}
24
Jayson Minard

それはほとんど私には大丈夫に見えます。私が行う唯一の違いは、ReadWriteで定義された " se "拡張を使用してライターを自動的に閉じることです。

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

最低限、次のものを使用できます。

FileWriter(filename).use { it.write(text) }

FileWriter は、文字ファイルを書き込むための便利なクラスです(Javaによって提供されるため、Kotlinで利用可能です)。 Closeableを拡張するため、Kotlinの「.use」拡張メソッドで使用できます。

。use 拡張メソッドは、ブロックが終了すると呼び出しオブジェクトを自動的に閉じるため、書き込み後にファイルを閉じる慣用的な方法を提供します。

2

一部の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)
    }
}
1
Vadzim
try{
      val fileWriter = FileWriter("test.txt", true)
      fileWriter.write(string+ "\n")
      fileWriter.close()
    } catch (exception: Exception){
        println(exception.message)
    }
0
Ajay Prajapati