InputStream
最近、 Kotlin で文字列の内容全体を読み込む次のようなコードを見ました。
// input is of type InputStream
val baos = ByteArrayOutputStream()
input.use { it.copyTo(baos) }
val inputAsString = baos.toString()
さらに:
val reader = BufferedReader(InputStreamReader(input))
try {
val results = StringBuilder()
while (true) {
val line = reader.readLine()
if (line == null) break
results.append(line)
}
val inputAsString = results.toString()
} finally {
reader.close()
}
さらに、自動的に閉じられるので、よりスムーズに見えますInputStream
。
val inputString = BufferedReader(InputStreamReader(input)).useLines { lines ->
val results = StringBuilder()
lines.forEach { results.append(it) }
results.toString()
}
あるいは、少しバリエーションをつけて:
val results = StringBuilder()
BufferedReader(InputStreamReader(input)).forEachLine { results.append(it) }
val resultsAsString = results.toString()
次に、この機能的な折り畳み機能について説明します。
val inputString = input.bufferedReader().useLines { lines ->
lines.fold(StringBuilder()) { buff, line -> buff.append(line) }.toString()
}
または悪いを閉じないバリエーションInputStream
:
val inputString = BufferedReader(InputStreamReader(input))
.lineSequence()
.fold(StringBuilder()) { buff, line -> buff.append(line) }
.toString()
しかし、それらはすべて不格好で、同じものの新しいバージョンや異なるバージョンが見つかり続けます...そして、それらのいくつかは を閉じることすらInputStream
ありません。 を読むための不格好でない(慣用的な)方法は何ですかInputStream
?
注記: この質問は著者によって意図的に書かれ、回答されています(自己回答形式の質問) なので、Kotlin に関するよくある質問に対する慣用的な回答が SO に掲載されています。
ベストアンサー1
Kotlin には、この目的専用の拡張機能があります。
もっとも単純な:
val inputAsString = input.bufferedReader().use { it.readText() } // defaults to UTF-8
bufferedReader()
この例では、または のどちらかを選択できますreader()
。関数の呼び出しCloseable.use()
ラムダの実行終了時に入力を自動的に閉じます。
参考文献:
この種のことを頻繁に行う場合は、これを拡張関数として記述できます。
fun InputStream.readTextAndClose(charset: Charset = Charsets.UTF_8): String {
return this.bufferedReader(charset).use { it.readText() }
}
これを次のように簡単に呼び出すことができます。
val inputAsString = input.readTextAndClose() // defaults to UTF-8
ちなみに、 を知る必要があるすべての Kotlin 拡張関数は、charset
すでに にデフォルト設定されているUTF-8
ため、別のエンコーディングが必要な場合は、 の呼び出しで上記のコードを調整して、reader(charset)
またはのエンコーディングを含める必要がありますbufferedReader(charset)
。
警告:より短い例が見られるかもしれません:
val inputAsString = input.reader().readText()
しかし、これらのストリームを閉じないでください必ず確認してくださいすべてのIO関数のAPIドキュメントどれが閉じてどれが閉じないかを確認するために使用します。通常、単語use
(またはuseLines()
などuse()
)が含まれている場合は、その後でストリームを閉じます。例外はFile.readText()
とは異なりReader.readText()
前者は何も未解決のままにせず、後者は確かに明示的な終了を必要とするという点で。
参照: Kotlin IO関連の拡張関数