我最近看到了将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
?
注意: 这个问题是由作者(Self-Answered Questions)故意编写和回答的,因此对于常见问题的Kotlin主题的惯用答案存在于SO中。
答案 0 :(得分:163)
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
默认为UTF-8
的Kotlin扩展函数,因此如果您需要不同的编码,则需要在调用中调整上面的代码以包含编码适用于reader(charset)
或bufferedReader(charset)
。
警告:您可能会看到更短的示例:
val inputAsString = input.reader().readText()
但是这些不会关闭流。请务必检查您使用的API documentation for all of the IO functions,以确定哪些关闭,哪些关闭。通常,如果它们包含单词use
(例如useLines()
或use()
),则会在之后关闭流。一个例外是File.readText()
与Reader.readText()
的不同之处在于前者不会留下任何东西,后者确实需要明确关闭。
答案 1 :(得分:1)
将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
答案 2 :(得分:0)
【方法1 |手动关闭流}
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 【方法2 |自动关闭流}
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()
的升级版,它的用途更广泛:
How exactly does bufferedReader() work in Kotlin?
use()
可以在块完成后自动关闭流:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html
答案 3 :(得分:-1)
快速解决方案在将 InputStream 转换为字符串时效果很好。
val convertedInputStream = String(inputStream.readAllBytes(), StandardCharsets.UTF_8)