Как именно работает bufferedReader () в Kotlin? - PullRequest
4 голосов
/ 04 апреля 2019

Итак, я пытаюсь прочитать данные из файла .json в моем проекте Android:

val file = context.assets.open("myfile.json").bufferedReader().readText()

Это прекрасно работает и успешно печатает мой .json файл как один String.

Однако я хочу знать, что именно является bufferedReader() и почему .readText() не может быть вызван непосредственно в открытом файле .json.

PS: readText() возвращает String. Тем не менее:

val json2: JSONObject = JSONObject("mystring") возвращает:

Caused by: org.json.JSONException: Value mystring of type java.lang.String cannot be converted to JSONObject

Как это имеет смысл?

Ответы [ 2 ]

5 голосов
/ 04 апреля 2019

Функция readText определяется как расширение для Reader:

public fun Reader.readText(): String {
    val buffer = StringWriter()
    copyTo(buffer)
    return buffer.toString()
}

InputStream не является Reader, поэтому вы должны преобразовать его в некоторый Reader:

public inline fun InputStream.reader(charset: Charset = Charsets.UTF_8): InputStreamReader = 
    InputStreamReader(this, charset)

Вы можете использовать ридер в качестве буферизованного ридера с альтернативной функцией bufferedReader:

public inline fun InputStream.bufferedReader(charset: Charset = Charsets.UTF_8): BufferedReader = 
    reader(charset).buffered()

Reader, а также BufferedReaderявляются частью стандартной библиотеки Java, и буферизованная версия описывается следующим образом:

Считывает текст из потока ввода символов, буферизует символы, чтобы обеспечить эффективное чтение символов, массивов иlines.

Как правило, каждый запрос чтения, выполненный устройством чтения, вызывает соответствующий запрос чтения базового символа или байтового потока.Поэтому желательно обернуть BufferedReader вокруг любого Reader, чьи операции read () могут быть дорогостоящими, например, FileReaders и InputStreamReaders ...

Он в основном оборачивает Reader и добавляет поддержку для чтения одноголинии и т. д.

3 голосов
/ 04 апреля 2019
val file = context.assets.open("myfile.json").bufferedReader().readText()

Вот код, который делает то же самое, что и строка выше.

val inputStream = context.assets.open("myfile.json")
val reader = inputStream.bufferedReader()
val file = reader.readText()

Предположим, что здесь содержится содержание myfile.json

{
    "os": "Android",
    "version": "KitKat",
    "codeName": 4.4
}

Давайте пройдемся по шагамstep

Step 1: Первая строка

val inputStream = context.assets.open("myfile.json")

Будет возвращен объект InputStream , который читает один байт или количество байтовиз файла JSON.Если вы распечатаете содержимое файла json в байтовом формате на экране, нам (программистам) будет очень трудно читать.

Шаг 2: Вторая строка

val reader = inputStream.bufferedReader()

Это создаст BufferedReader объект, который читает символ или количество символов из файла json, но у них есть другой полезный метод с именем readLine () , этот методчитает строку текста.Строка считается завершенной любым из перевода строки ('\ n'), возврата каретки ('\ r') или возврата каретки, за которым сразу следует перевод строки.

Давайте изменимтекущий код.

val inputStream = context.assets.open("myfile.json")
val reader = inputStream.bufferedReader()

// Read line by line from reader until reach the end.
var line = reader.readLine()
while(line != null) {
    Log.i("TAG", line)
    line = reader.readLine()
}

Вывод:

I/TAG: {
I/TAG:     "os": "Android",
I/TAG:     "version": "KitKat",
I/TAG:     "codeName": 4.4
I/TAG: }

Как мы видим, они печатают 5 строк из файла json.Но в некоторых случаях мы хотим напечатать весь файл json в виде строки, поэтому перейдем к следующему шагу.

Шаг 3: Третья строка

val file = reader.readText()

Это полностью считывает буфер чтения как String.Вы можете написать свой собственный, чтобы сделать то же самое, как.

val inputStream = context.assets.open("myfile.json")
val reader = inputStream.bufferedReader()

val sb = StringBuffer()

var line = reader.readLine()
while(line != null) {
    Log.i("TAG", line)
    sb.append(line).append("\n")
    line = reader.readLine()
}

val file = sb.toString()

Log.i("TAG", file)

Вывод:

I/TAG: {
        "os": "Android",
        "version": "KitKat",
        "codeName": 4.4
}

Этот вывод такой же, как reader.readText().

Вывод: BufferReader оборачивает InputStream (или подклассы InputStream) внутри них, а затем предоставляет методы для считывания посимвольных символов вместо побайтных в InputStream.Кроме того, они предоставляют метод readLine (), буферизующий данные.

InputStream (побайтовый) -> Reader (посимвольный)

InputStream (byte-by-byte) -> BufferReader (символьный символ, строка чтения, данные буфера).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...