В Kotlin, как я могу прочитать все содержимое InputStream в String?

Недавно я видел код для чтения всего содержимого InputStream в String в 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 ?

Примечание: этот вопрос намеренно написан автором и автору ( ответы на вопросы ), так что идиоматические ответы на часто задаваемые темы Котлина присутствуют в SO.

    Для этой цели у Kotlin есть определенные расширения.

    Простейший:

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

    И в этом примере вы можете выбрать между bufferedReader() или просто reader() . Вызов функции Closeable.use() будет автоматически закрывать вход в конце выполнения лямбда.

    Дальнейшее чтение:

    Если вы так много делаете, вы можете написать это как функцию расширения:

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

    Что вы могли бы тогда легко вызвать:

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

    С другой стороны, все функции расширения Kotlin, которые требуют знания charset уже по умолчанию имеют UTF-8 , поэтому, если вам требуется другая кодировка, вам нужно настроить код выше в вызовах, чтобы включить кодировку для reader(charset) или bufferedReader(charset) .

    Предупреждение. Вы можете увидеть примеры, которые короче:

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

    Но они не закрывают поток . Убедитесь, что вы проверяете документацию API для всех функций ввода-вывода, которые вы используете, чтобы убедиться, какие из них закрыты, а какие нет. Обычно, если они включают использование слова (например, useLines() или use() ), вы закрываете поток после. Исключением является то, что File.readText() отличается от Reader.readText() тем, что первое не оставляет ничего открытого, а последнее действительно требует явного закрытия.

    См. Также: Функции расширения, связанные с Iot Kotlin

    Пример, который читает содержимое InputStream для строки

     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