在Kotlin中使用BufferedReader的最佳方法

57

我刚刚开始使用Kotlin开发Android应用,并将我的Java Android代码转换为Kotlin。

在其中一个转换中,我遇到了一个BufferedReader,它原本在Java中的写法是:

String result = "";
String line = "";
BufferedReader reader = new BufferedReader(someStream);
while ( (line = reader.readLine()) != null ) {
    result += line;
}
但是在 Kotlin 中,似乎 Kotlin 不允许我在 while 循环条件中赋值给变量。
目前,我的代码如下所示:
val reader = BufferedReader(someStream)
var line : String? = ""
while (line != null) {
    line = reader.readLine()
    result += line
}

尽管使用Kotlin,但我认为它不够优雅,感觉上一代。

在Kotlin中使用BufferedReader的最佳方式是什么?

9个回答

99
您可以这样使用bufferedReader
val allText = inputStream.bufferedReader().use(BufferedReader::readText)

3
一个解释:https://kotlinlang.org/docs/reference/idioms.html#java-7s-try-with-resources - voddan

24

如果您仍然想逐行阅读它,您可以使用标准库的一些扩展函数来执行以下操作:

val reader = someStream.bufferedReader()
val iterator = reader.linesSequences().iterator()
while(iterator.hasNext()) {
    val line = iterator.next()
    // do something with line...
}
reader.close()

或者,使用“函数式”方法:

val reader = someStream.bufferedReader()
reader.useLines {
    it.map { line -> // do something with line }
}

通过使用useLines,您无需显式调用读取器的close方法,useLines扩展函数会替您完成!

仅供参考。谢谢。


useLines 会一次性加载所有行吗?如果我要读取一个大文件,那么这会使用太多内存吗?还是每次只获取需要的行?谢谢。 - AurumTechie
1
使用 useLines 可以使用一个序列,该序列使用流上的惰性评估,对于打开的文件句柄数量很好。Jetbrains建议使用 File.forEachLine 处理大文件,其中每次处理一行(https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-file/for-each-line.html)。但是,在底层,File.forEachLine 仍然使用相同默认缓冲区大小为8 * 1024 的 useLines。 - baseman

22

您也可以尝试使用“forEachLine”方法。

val file = File("./folder/test.txt")
file.bufferedReader().forEachLine {
    println("value = $it")
} 

当使用Reader.forEachLine方法迭代读取每一行数据时,它会自动在读取完最后一行后关闭输入流。

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-reader/index.html

fun Reader.forEachLine(action: (String) -> Unit)
迭代读取此读取器的每一行数据,并在读取完成后关闭读取器。


5

另一种方法是使用for循环:

val reader = BufferedReader(someStream)
for (line in reader.lines()) {
    println(line)
}

虽然它不像被接受的答案那样简洁,但它允许您循环执行某种逻辑,而无需将所有内容都输入到一个字符串中,如下所示。
val allText: String = inputStream.bufferedReader().use(BufferedReader::readText)

2
请注意:您可以使用useLines()方法迭代行,该方法返回一个惰性的Sequence<String>并为您关闭底层的BufferedReader。 - blahblah

2
由于João Gonçalves提到了stdlib,我发现您可以使用forEachLine来遍历读取器(reader)(如果需要的话)。

1

像这样使用代码

    val input = conn.inputStream
    val allText = input.bufferedReader().use(BufferedReader::readText)
    val result = StringBuilder()
result.append(allText) return result.toString()
} else {
return "失败"
}

1
您可以像这样使用BufferReader:

< / p>

val data = inputStream.bufferedReader().use(BufferedReader::readText)
    

1
你的解决方案与被接受的答案有何不同? - tronman

1

当流有多行时,被接受的答案会失败。这是我的解决方案。

val allText = inputStream.bufferedReader().use { it.readLines().joinToString("") }

0

该解决方案在每行末尾包含字符 \n

val fileInputStream = context.openFileInput(fileName)
val reader = BufferedReader(InputStreamReader(fileInputStream))
val line = reader.buffered().use { it.readText() }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接