在Kotlin中bufferedReader()到底如何工作?

时间:2019-04-04 08:13:40

标签: android json kotlin

因此,我正在尝试从Android项目中的.json文件中读取数据:

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 个答案:

答案 0 :(得分:5)

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

ReaderBufferedReader都是Java标准库的一部分,缓冲版本的描述如下:

  

从字符输入流中读取文本,缓冲字符以便   提供有效读取字符,数组和行的方法。

     

通常,由读取器发出的每个读取请求都会导致对基础字符或字节流进行相应的读取请求。它是    因此建议将BufferedReader包装在其read()的所有Reader周围    操作可能很昂贵,例如FileReaders和InputStreamReaders ...

它基本上包装了Reader并增加了对读取单行等的支持。

答案 1 :(得分:3)

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
}

让我们一步一步走

步骤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: }

我们可以看到,它们从json文件中打印5行。但是在某些情况下,我们希望将所有json文件打印为String,这就是为什么我们要进行下一步的原因。

步骤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(逐字节)->阅读器(逐个字符)

     

InputStream(逐字节)-> BufferReader(逐个字符,   读取行,缓冲数据)。