在 Kotlin 中,如何将 InputStream 的全部内容读入字符串? [英] In Kotlin, how do I read the entire contents of an InputStream into a String?

查看:47
本文介绍了在 Kotlin 中,如何将 InputStream 的全部内容读入字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近看到在 Kotlin 中将 InputStream 的全部内容读入字符串的代码,例如:

I recently saw code for reading entire contents of an InputStream into a String in Kotlin, such as:

// 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:

And even this that looks smoother since it auto-closes the 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()   

然后这个功能折叠的东西:

Then this functional fold thingy:

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 的非笨拙(惯用)方式?

But they are all clunky and I keep finding newer and different versions of the same... and some of them never even close the InputStream. What is a non-clunky (idiomatic) way to read the InputStream?

注意:这个问题是作者有意编写和回答的(Self-Answered Questions),以便在 SO 中出现对 Kotlin 常见问题的惯用答案.

Note: this question is intentionally written and answered by the author (Self-Answered Questions), so that the idiomatic answers to commonly asked Kotlin topics are present in SO.

推荐答案

Kotlin 有一个专门用于此目的的扩展.

Kotlin has a specific extension just for this purpose.

最简单的:

val inputAsString = input.bufferedReader().use { it.readText() }  // defaults to UTF-8

在本例中,您可以选择 bufferedReader()reader().对函数的调用 Closeable.use() 将在 lambda 执行结束时自动关闭输入.

And in this example, you could decide between bufferedReader() or just reader(). The call to the function Closeable.use() will automatically close the input at the end of the lambda's execution.

进一步阅读:

如果你经常做这类事情,你可以把它写成一个扩展函数:

If you do this type of thing a lot, you could write this as an extension function:

fun InputStream.readTextAndClose(charset: Charset = Charsets.UTF_8): String {
    return this.bufferedReader(charset).use { it.readText() }
}

然后您可以轻松调用它:

Which you could then call easily as:

val inputAsString = input.readTextAndClose()  // defaults to UTF-8

附带说明,所有需要知道 charset 的 Kotlin 扩展函数已经默认为 UTF-8,因此如果您需要不同的编码,则需要调整上面的代码在调用中包含 reader(charset)bufferedReader(charset) 的编码.

On a side note, all Kotlin extension functions that require knowing the charset already default to UTF-8, so if you require a different encoding you need to adjust the code above in calls to include encoding for reader(charset) or bufferedReader(charset).

警告:您可能会看到较短的示例:

Warning: You might see examples that are shorter:

val inputAsString = input.reader().readText() 

但是这些不会关闭流.请务必查看 所有 IO 功能的 API 文档 你用来确定哪些关闭,哪些不关闭.通常,如果它们包含单词 use(例如 useLines()use()),它们会在之后关闭流.一个例外是 File.readText() 不同于 Reader.readText() 因为前者没有打开任何东西,而后者确实需要显式关闭.

But these do not close the stream. Make sure you check the API documentation for all of the IO functions you use to be sure which ones close and which do not. Usually, if they include the word use (such as useLines() or use()) they close the stream after. An exception is that File.readText() differs from Reader.readText() in that the former does not leave anything open and the latter does indeed require an explicit close.

另见: Kotlin IO相关扩展功能

这篇关于在 Kotlin 中,如何将 InputStream 的全部内容读入字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆