inputstream kotlin

En Kotlin, ¿cómo leo todo el contenido de un InputStream en una cadena?



(2)

Kotlin tiene extensiones específicas solo para este propósito.

Lo más simple:

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

Y en este ejemplo, podría decidir entre bufferedReader() o solo reader() . La llamada a la función Closeable.use() cerrará automáticamente la entrada al final de la ejecución de lambda.

Otras lecturas:

Si haces mucho este tipo de cosas, podrías escribir esto como una función de extensión:

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

Que luego podría llamar fácilmente como:

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

En una nota al margen, todas las funciones de extensión de Kotlin que requieren conocer el UTF-8 charset ya tienen el valor predeterminado UTF-8 , por lo que si necesita una codificación diferente, debe ajustar el código anterior en las llamadas para incluir una codificación para el reader(charset) o bufferedReader(charset)

Advertencia: puede ver ejemplos que son más cortos:

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

Pero estos no cierran la corriente . Asegúrese de consultar la documentación de la API para ver todas las funciones de E / S que utiliza para asegurarse de cuáles se cierran y cuáles no. Por lo general, si incluyen la palabra use (como useLines() o use() ), cierra la secuencia después. Una excepción es que File.readText() difiere de Reader.readText() en que el primero no deja nada abierto y el último requiere un cierre explícito.

Consulte también: Funciones de extensión relacionadas con Kotlin IO

Recientemente vi código para leer todo el contenido de un InputStream en una cadena en Kotlin, como:

// input is of type InputStream val baos = ByteArrayOutputStream() input.use { it.copyTo(baos) } val inputAsString = baos.toString()

Y también:

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() }

E incluso esto se ve más suave ya que cierra automáticamente el InputStream :

val inputString = BufferedReader(InputStreamReader(input)).useLines { lines -> val results = StringBuilder() lines.forEach { results.append(it) } results.toString() }

O una ligera variación en ese:

val results = StringBuilder() BufferedReader(InputStreamReader(input)).forEachLine { results.append(it) } val resultsAsString = results.toString()

Entonces, este doblez funcional:

val inputString = input.bufferedReader().useLines { lines -> lines.fold(StringBuilder()) { buff, line -> buff.append(line) }.toString() }

O una mala variación que no cierra InputStream :

val inputString = BufferedReader(InputStreamReader(input)) .lineSequence() .fold(StringBuilder()) { buff, line -> buff.append(line) } .toString()

Pero todos son torpes y sigo encontrando versiones más nuevas y diferentes de los mismos ... y algunos de ellos ni siquiera cierran el InputStream . ¿Cuál es una forma no torpe (idiomática) de leer InputStream ?

Nota: esta pregunta está escrita y respondida intencionalmente por el autor ( Preguntas con respuesta propia ), de modo que las respuestas idiomáticas a los temas de Kotlin más frecuentes están presentes en SO.


Un ejemplo que lee el contenido de un InputStream en una cadena

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) }

Para referencia - Kotlin Read File