InputStream to String in Kotlin

1. Übersicht

In diesem kurzen Tutorial erfahren Sie, wie Sie einen InputStream in einen String einlesen .

Kotlin bietet eine einfache Möglichkeit, die Konvertierung durchzuführen. Bei der Arbeit mit Ressourcen sind jedoch noch einige Nuancen zu berücksichtigen. Außerdem behandeln wir Sonderfälle wie das Lesen bis zu einem Stoppzeichen .

2. Gepufferter Leser

InputStream ist eine Abstraktion um einen geordneten Bytestrom . Eine zugrunde liegende Datenquelle kann eine Datei, eine Netzwerkverbindung oder eine andere Quelle sein, die Bytes emittiert. Verwenden wir eine einfache Datei, die die folgenden Daten enthält:

Computer programming can be a hassle It's like trying to take a defended castle

Die erste Lösung, die wir versuchen könnten, besteht darin, die Datei manuell Zeile für Zeile zu lesen:

val reader = BufferedReader(inputStream.reader()) val content = StringBuilder() try { var line = reader.readLine() while (line != null) { content.append(line) line = reader.readLine() } } finally { reader.close() }

Zuerst haben wir die BufferedReader- Klasse verwendet, um den InputStream zu verpacken und dann zu lesen, bis keine Zeilen mehr im Stream vorhanden sind. Darüber hinaus haben wir die Leselogik von der try-finally- Anweisung umgeben, um den Stream endgültig zu schließen . Insgesamt gibt es viel Boilerplate-Code.

Könnten wir es kompakter und lesbarer machen?

Absolut! Zunächst können wir das Snippet mithilfe der Funktion readText () vereinfachen . Es liest den Eingabestream vollständig als String . Dementsprechend können wir unser Snippet wie folgt umgestalten:

val reader = BufferedReader(inputStream.reader()) var content: String try { content = reader.readText() } finally { reader.close() }

Wir haben jedoch immer noch diesen Try-finally- Block. Glücklicherweise ermöglicht Kotlin die pseudoautomatische Handhabung des Ressourcenmanagements. Schauen wir uns die nächsten Codezeilen an:

val content = inputStream.bufferedReader().use(BufferedReader::readText) assertEquals(fileFullContent, content) 

Diese einzeilige Lösung sieht einfach aus, dennoch passiert viel unter der Haube. Ein wichtiger Punkt im obigen Code ist der Aufruf der Funktion use () . Diese Erweiterungsfunktion führt einen Block für eine Ressource aus, die die Closable- Schnittstelle implementiert . Schließlich, wenn der Block ausgeführt wird, schließt Kotlin die Ressource für uns.

3. Stopp Charakter

Gleichzeitig kann es vorkommen, dass wir Inhalte bis zu einem bestimmten Zeichen lesen müssen . Definieren wir eine Erweiterungsfunktion für die InputStream- Klasse:

fun InputStream.readUpToChar(stopChar: Char): String { val stringBuilder = StringBuilder() var currentChar = this.read().toChar() while (currentChar != stopChar) { stringBuilder.append(currentChar) currentChar = this.read().toChar() if (this.available() <= 0) { stringBuilder.append(currentChar) break } } return stringBuilder.toString() }

Diese Funktion liest Bytes aus einem Eingabestream, bis ein Stoppzeichen angezeigt wird . Um die Endlosschleife zu verhindern, rufen wir gleichzeitig die Methode available () auf, um zu überprüfen, ob im Stream noch Daten vorhanden sind. Wenn ein Stream kein Stoppzeichen enthält, wird ein ganzer Stream gelesen.

Andererseits bieten nicht alle Unterklassen der InputStream- Klasse eine Implementierung für die Methode available () . Folglich müssen wir sicherstellen, dass die Methode korrekt implementiert ist, bevor wir die Erweiterungsfunktion verwenden.

Kehren wir zu unserem Beispiel zurück und lesen Sie den Text bis zum ersten Leerzeichen (''):

val content = inputStream.use { it.readUpToChar(' ') } assertEquals("Computer", content) 

Als Ergebnis erhalten wir den Text bis zum Stoppzeichen. Vergessen Sie auf die gleiche Weise nicht, den Block mit der Funktion use () zu umschließen, um den Stream automatisch zu schließen .

4. Fazit

In diesem Artikel haben wir gesehen, wie ein InputStream in Kotlin in einen String konvertiert wird . Kotlin bietet eine präzise Möglichkeit, mit Datenströmen zu arbeiten, aber es lohnt sich immer zu wissen, was intern vor sich geht.

Wie üblich ist die Implementierung all dieser Beispiele auf Github beendet.