我最近看到了用于将 InputStream
的全部内容读入Kotlin中的String的代码,例如:
// 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()
}
或者 bad 变体没有关闭 InputStream
:
val inputString = BufferedReader(InputStreamReader(input))
.lineSequence()
.fold(StringBuilder()) { buff, line -> buff.append(line) }
.toString()
但它们都很笨重,而且我一直在寻找相同的新版本和不同版本...而其中一些版本甚至从未关闭 InputStream
. 什么是非笨重(惯用)的方式来阅读 InputStream
?
Note: 这个问题是由作者故意编写和回答的(Self-Answered Questions),因此对于常见问题的Kotlin主题的惯用答案存在于SO中 .
2 回答
Kotlin只是为了这个目的而有一个特定的扩展 .
The simplest:
在这个例子中,您可以在
bufferedReader()
或reader()
之间做出决定 . 对函数Closeable.use()的调用将在lambda执行结束时自动关闭输入 .Further reading:
如果你做了很多类型的事情,你可以把它写成一个扩展函数:
然后您可以轻松调用:
另外,所有Kotlin扩展函数都需要知道
charset
已默认为UTF-8
,因此如果您需要不同的编码,则需要在调用中调整上面的代码以包含reader(charset)
或bufferedReader(charset)
的编码 .Warning: 您可能会看到更短的示例:
但这些 do not close the stream . 请务必检查您使用的API documentation for all of the IO functions以确定哪些关闭,哪些关闭 . 通常如果它们包含单词
use
(例如useLines()
或use()
),则关闭流后 . 一个例外是File.readText()与Reader.readText()的不同之处在于,前者不会留下任何打开,后者确实需要明确关闭 .See also: Kotlin IO related extension functions
将InputStream的内容读取到String的示例
供参考 - Kotlin Read File