最近,我在Kotlin中看到了用于将InputStream
的全部内容读取为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()
}
或较差的变体形式,但没有关闭
InputStream
:val inputString = BufferedReader(InputStreamReader(input))
.lineSequence()
.fold(StringBuilder()) { buff, line -> buff.append(line) }
.toString()
但是它们都很笨拙,而且我一直在寻找相同的更新和不同版本...并且其中一些甚至从未关闭
InputStream
。什么是读取InputStream
的非笨拙(惯用)方法?注意:这个问题是作者故意写和回答的(Self-Answered Questions),因此SO中常见的Kotlin主题的惯用答案。
最佳答案
Kotlin为此有一个特定的扩展。
最简单的方法:
val inputAsString = input.bufferedReader().use { it.readText() } // defaults to UTF-8
在此示例中,您可以在
bufferedReader()
或reader()
之间进行选择。调用函数 Closeable.use()
将在lambda执行结束时自动关闭输入。进一步阅读:
如果您经常执行此类操作,则可以将其编写为扩展函数:
fun InputStream.readTextAndClose(charset: Charset = Charsets.UTF_8): String {
return this.bufferedReader(charset).use { it.readText() }
}
然后您可以轻松地将其称为:
val inputAsString = input.readTextAndClose() // defaults to UTF-8
附带说明一下,所有需要知道
charset
的Kotlin扩展功能已经默认为UTF-8
,因此,如果您需要其他编码,则需要在调用中调整以上代码以包括reader(charset)
或bufferedReader(charset)
的编码。警告:您可能会看到简短的示例:
val inputAsString = input.reader().readText()
但是这些不会关闭流。确保检查使用的API documentation for all of the IO functions,以确保哪些关闭,哪些不关闭。通常,如果它们包含单词
use
(例如useLines()
或use()
),请在之后关闭流。一个异常(exception)是 File.readText()
与 Reader.readText()
的不同之处在于,前者没有打开任何东西,而后者确实需要显式关闭。另请参见: Kotlin IO related extension functions