InputStream su String in Kotlin

1. Panoramica

In questo breve tutorial, scopriremo come leggere un InputStream in una stringa.

Kotlin fornisce un modo semplice per eseguire la conversione. Tuttavia, ci sono ancora alcune sfumature da considerare quando si lavora con le risorse. Inoltre, tratteremo casi speciali, come leggere fino a un carattere di arresto .

2. Lettore bufferizzato

InputStream è un'astrazione attorno a un flusso ordinato di byte . Una sorgente dati sottostante può essere un file, una connessione di rete o qualsiasi altra sorgente che emette byte. Usiamo un semplice file che contiene i seguenti dati:

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

La prima soluzione che potremmo provare è leggere il file manualmente riga per riga:

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

Per prima cosa, abbiamo usato la classe BufferedReader per avvolgere InputStream e quindi leggere fino a quando non sono rimaste righe nel flusso. Inoltre, abbiamo circondato la logica di lettura con l' istruzione try- latest per chiudere definitivamente il flusso . Complessivamente, c'è molto codice boilerplate.

Potremmo renderlo più compatto e leggibile?

Assolutamente! All'inizio, possiamo semplificare lo snippet usando la funzione readText () . Legge il flusso di input completamente come una stringa . Di conseguenza, possiamo eseguire il refactoring del nostro snippet come segue:

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

Tuttavia, abbiamo ancora quel blocco di prova finale . Fortunatamente, Kotlin consente di gestire la gestione delle risorse in modo pseudo-automatico. Diamo un'occhiata alle prossime righe di codice:

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

Questa soluzione a una riga sembra semplice, tuttavia, molte cose stanno accadendo sotto il cofano. Un punto importante nel codice sopra è la chiamata della funzione use () . Questa funzione di estensione esegue un blocco su una risorsa che implementa l' interfaccia Closable . Infine, quando il blocco viene eseguito, Kotlin chiude la risorsa per noi.

3. Stop Character

Allo stesso tempo, potrebbe esserci un caso in cui dobbiamo leggere il contenuto fino a un carattere specifico . Definiamo una funzione di estensione per 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() }

Questa funzione legge i byte da un flusso di input finché non viene visualizzato un carattere di interruzione . Allo stesso tempo, per prevenire il ciclo infinito, chiamiamo il metodo available () per verificare se il flusso ha ancora dei dati. Quindi, se non ci sono caratteri di interruzione in un flusso, verrà letto un intero flusso.

D'altra parte, non tutte le sottoclassi della classe InputStream forniscono un'implementazione per il metodo available () . Di conseguenza, dobbiamo assicurarci che il metodo sia implementato correttamente prima di utilizzare la funzione di estensione.

Torniamo al nostro esempio e leggiamo il testo fino al primo carattere di spazio bianco (''):

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

Di conseguenza, porteremo il testo fino al carattere di arresto. Allo stesso modo, non dimenticare di avvolgere il blocco con la funzione use () per chiudere automaticamente lo stream .

4. Conclusione

In questo articolo, abbiamo visto come convertire un InputStream in una stringa in Kotlin. Kotlin fornisce un modo conciso per lavorare con flussi di dati, ma vale sempre la pena sapere cosa sta succedendo internamente.

Come al solito, l'implementazione di tutti questi esempi è finita su Github.