2016-09-14 47 views
33

我最近看到的代码读取InputStream的全部内容复制到在科特林一个字符串,如:在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),从而使惯用解答常见科特林主题存在于SO。

回答

75

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()),那么请关闭该流。 File.readText()Reader.readText()不同之处在于,前者不留任何开放,后者确实需要明确的关闭。

参见:Kotlin IO related extension functions

+1

我觉得 “READTEXT” 会比一个更好的名字“useText”用于您提出的扩展功能。当我读取“useText”时,我期望有一个像use或useLines这样的函数,它对正在使用的内容执行块函数。例如'inputStream.useText {text - > ...}另一方面,当我读取“readText”时,我期待一个返回文本的函数:'val inputAsString = inputStream.readText()'。 – mfulton26

+0

确实如此,但readText已经有错误的含义,所以想要表示它更像是在这方面的'使用'功能。至少在这个问答环境中。也许可以找到一个新的动词...... –

+2

@ mfulton26为了避免与'readText()'不关闭的模式冲突,并且''use''模式想要一个lambda,我使用'readTextAndClose我不想介绍一个新的stdlib函数,我不想做更多关于使用扩展来保存未来劳动力的观点。 –

0

读取的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

相关问题