InputStream към String в Kotlin

1. Общ преглед

В този кратък урок ще разберем как да четем InputStream в низ.

Kotlin осигурява лесен начин за извършване на преобразуването. Все пак има някои нюанси, които трябва да се вземат предвид при работа с ресурси. Освен това ще разгледаме специални случаи, като четене до спиране на знака .

2. Буфериран четец

InputStream е абстракция около подреден поток байтове . Основният източник на данни може да бъде файл, мрежова връзка или друг източник, излъчващ байтове. Нека използваме прост файл, който съдържа следните данни:

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

Първото решение, което бихме могли да опитаме, е да прочетем файла ръчно ред по ред:

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

На първо място, ние използвахме BufferedReader класа за увиване на InputStream и след това се чете, докато не линии, останали в потока. Освен това заобиколихме логиката за четене чрез изпитанието try-final , за да затворим окончателно потока . Като цяло има много типови кодове.

Можем ли да го направим по-компактен и четим?

Абсолютно! Отначало можем да опростим фрагмента, като използваме функцията readText () . Той чете входния поток напълно като низ . Съответно можем да рефакторираме нашия фрагмент, както следва:

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

Все още имаме този блок за опити-накрая . За щастие Kotlin позволява да се управлява управлението на ресурсите по псевдоавтоматичен начин. Нека да разгледаме следващите кодови редове:

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

Това еднолинейно решение изглежда просто, въпреки това много се случва под капака. Един важен момент в горния код е извикването на функцията use () . Тази функция за разширение изпълнява блок на ресурс, който реализира затварящ се интерфейс. И накрая, когато блокът бъде изпълнен, Kotlin затваря ресурса за нас.

3. Спиране на символа

В същото време може да има случай, когато трябва да прочетем съдържание до определен характер . Нека дефинираме функция за разширение за класа 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() }

Тази функция чете байтове от входния поток, докато се появи знак за спиране . В същото време, за да предотвратим безкрайния цикъл, извикваме метода available () , за да проверим дали в потока има останали данни. Така че, ако в поток няма знак за спиране, тогава ще бъде прочетен цял поток.

От друга страна, не всички подкласове от класа InputStream предоставят изпълнение за метода available () . Следователно трябва да гарантираме, че методът е изпълнен правилно, преди да използваме функцията за разширение.

Да се ​​върнем към нашия пример и да прочетем текст до първия пробел (""):

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

В резултат на това ще получим текста до символа за спиране. По същия начин, не забравяйте да увиете блока с функцията use (), за да затворите автоматично потока .

4. Заключение

В тази статия видяхме как да конвертираме InputStream в низ в Kotlin. Kotlin предоставя кратък начин за работа с потоци от данни, но винаги си струва да знаете какво се случва вътрешно.

Както обикновено, изпълнението на всички тези примери е приключило на Github.