InputStream to String dans Kotlin

1. Vue d'ensemble

Dans ce bref didacticiel, nous découvrirons comment lire un InputStream dans une chaîne.

Kotlin fournit un moyen simple d'effectuer la conversion. Cependant, il y a encore quelques nuances à considérer lorsque vous travaillez avec des ressources. De plus, nous couvrirons des cas particuliers, comme la lecture d'un caractère d'arrêt .

2. Lecteur tamponné

InputStream est une abstraction autour d'un flux ordonné d'octets . Une source de données sous-jacente peut être un fichier, une connexion réseau ou toute autre source émettant des octets. Utilisons un fichier simple contenant les données suivantes:

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

La première solution que nous pourrions essayer est de lire le fichier manuellement ligne par ligne:

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

Tout d'abord, nous avons utilisé la classe BufferedReader pour encapsuler le InputStream , puis nous avons lu jusqu'à ce qu'il ne reste plus de lignes dans le flux. De plus, nous avons entouré la logique de lecture de l' instruction try-finally pour finalement fermer le flux . Dans l'ensemble, il y a beaucoup de code standard.

Pourrions-nous le rendre plus compact et plus lisible?

Absolument! Dans un premier temps, nous pouvons simplifier l'extrait de code en utilisant la fonction readText () . Il lit complètement le flux d'entrée sous forme de chaîne . En conséquence, nous pouvons refactoriser notre extrait de code comme suit:

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

Cependant, nous avons toujours ce bloc try-finally . Heureusement, Kotlin permet de gérer la gestion des ressources de manière pseudo-automatique. Regardons les prochaines lignes de code:

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

Cette solution en une ligne semble simple, mais il se passe beaucoup de choses sous le capot. Un point important dans le code ci-dessus est l'appel de la fonction use () . Cette fonction d'extension exécute un bloc sur une ressource qui implémente l' interface Closable . Enfin, lorsque le bloc est exécuté, Kotlin ferme la ressource pour nous.

3. Arrêter le personnage

Dans le même temps, il peut y avoir un cas où nous devons lire du contenu jusqu'à un caractère spécifique . Définissons une fonction d'extension pour la classe InputStream :

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

Cette fonction lit les octets d'un flux d'entrée jusqu'à ce qu'un caractère d'arrêt apparaisse . En même temps, afin d'éviter la boucle infinie, nous appelons la méthode available () pour vérifier s'il reste des données dans le flux. Donc, s'il n'y a pas de caractère d'arrêt dans un flux, alors un flux entier sera lu.

En revanche, toutes les sous-classes de la classe InputStream ne fournissent pas d'implémentation pour la méthode available () . Par conséquent, nous devons nous assurer que la méthode est correctement implémentée avant d'utiliser la fonction d'extension.

Revenons à notre exemple et lisons le texte jusqu'au premier caractère d'espacement (''):

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

En conséquence, nous obtiendrons le texte jusqu'au caractère d'arrêt. De la même manière, n'oubliez pas d' envelopper le bloc avec la fonction use () pour fermer automatiquement le flux .

4. Conclusion

Dans cet article, nous avons vu comment convertir un InputStream en String dans Kotlin. Kotlin fournit un moyen concis de travailler avec des flux de données, mais il vaut toujours la peine de savoir ce qui se passe en interne.

Comme d'habitude, l'implémentation de tous ces exemples est terminée sur Github.