在 Kotlin 中,如何将 InputStream 的全部内容读入 String?
In Kotlin, how do I read the entire contents of an InputStream into a String?
我最近看到在 Kotlin 中将 InputStream
的全部内容读入字符串的代码,例如:
// 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)特意写下并回答的,以便对常见的 Kotlin 主题进行地道的回答存在于 SO 中。
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 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()
,因为前者不会打开任何东西,而后者确实需要明确关闭。
将 InputStream 的内容读取到 String 的示例
import java.io.File
import java.io.InputStream
import java.nio.charset.Charset
fun main(args: Array<String>) {
val file = File("input"+File.separator+"contents.txt")
var ins:InputStream = file.inputStream()
var content = ins.readBytes().toString(Charset.defaultCharset())
println(content)
}
供参考 - Kotlin Read File
【方法一 |手动关闭流】
private fun getFileText(uri: Uri):String {
val inputStream = contentResolver.openInputStream(uri)!!
val bytes = inputStream.readBytes() //see below
val text = String(bytes, StandardCharsets.UTF_8) //specify charset
inputStream.close()
return text
}
inputStream.readBytes()
需要手动关闭流:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-input-stream/read-bytes.html
【方法二 |自动关闭流】
private fun getFileText(uri: Uri): String {
return contentResolver.openInputStream(uri)!!.bufferedReader().use {it.readText() }
}
可以在bufferedReader()
里面指定字符集,默认是UTF-8
:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-input-stream/buffered-reader.html
bufferedReader()
是reader()
的升级版,用途更广:
use()
可以在块完成时自动关闭流:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html
快速解决方案在将 InputStream 转换为字符串时效果很好。
val convertedInputStream = String(inputStream.readAllBytes(), StandardCharsets.UTF_8)
我最近看到在 Kotlin 中将 InputStream
的全部内容读入字符串的代码,例如:
// 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)特意写下并回答的,以便对常见的 Kotlin 主题进行地道的回答存在于 SO 中。
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 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()
,因为前者不会打开任何东西,而后者确实需要明确关闭。
将 InputStream 的内容读取到 String 的示例
import java.io.File
import java.io.InputStream
import java.nio.charset.Charset
fun main(args: Array<String>) {
val file = File("input"+File.separator+"contents.txt")
var ins:InputStream = file.inputStream()
var content = ins.readBytes().toString(Charset.defaultCharset())
println(content)
}
供参考 - Kotlin Read File
【方法一 |手动关闭流】
private fun getFileText(uri: Uri):String {
val inputStream = contentResolver.openInputStream(uri)!!
val bytes = inputStream.readBytes() //see below
val text = String(bytes, StandardCharsets.UTF_8) //specify charset
inputStream.close()
return text
}
inputStream.readBytes()
需要手动关闭流:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-input-stream/read-bytes.html
【方法二 |自动关闭流】
private fun getFileText(uri: Uri): String {
return contentResolver.openInputStream(uri)!!.bufferedReader().use {it.readText() }
}
可以在
bufferedReader()
里面指定字符集,默认是UTF-8
: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-input-stream/buffered-reader.htmlbufferedReader()
是reader()
的升级版,用途更广:use()
可以在块完成时自动关闭流: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html
快速解决方案在将 InputStream 转换为字符串时效果很好。
val convertedInputStream = String(inputStream.readAllBytes(), StandardCharsets.UTF_8)