如何在Go

时间:2015-08-06 14:04:06

标签: json parsing go io

我有一些我要解析的大型json文件,我想避免一次将所有数据加载到内存中。我喜欢一个函数/循环,它可以一次一个地返回每个角色。

我发现this example用于迭代字符串中的单词,而bufio包中的the ScanRunes函数看起来可能一次返回一个字符。我也有bufio的ReadRune函数主要工作,但这感觉就像一个非常沉重的方法。

修改

我比较了3种方法。所有人都使用循环来从bufio.Reader或bufio.Scanner中提取内容。

  1. 使用.ReadRune上的bufio.Reader在循环中读取符文。检查了.ReadRune
  2. 的来电错误
  3. 在扫描仪上调用bufio.Scanner后,从.Split(bufio.ScanRunes)读取字节。在每次迭代时调用.Scan.Bytes,检查.Scan是否需要调用错误。
  4. 与#2相同,但使用.Textbufio.Scanner而不是字节读取文本。我没有用string([]runes)加入一片符文,而是用strings.Join([]strings, "")加入了一段字符串,以形成最后的文本blob。
  5. 23 MB json文件上每次运行10次的时间是:

    1. 0.65 s
    2. 2.40 s
    3. 0.97 s
    4. 所以看起来ReadRune毕竟不是太糟糕。它还会导致较小的详细调用,因为每个符文都是在1次操作(.ReadRune)而不是2次(.Scan.Bytes)中获取的。

3 个答案:

答案 0 :(得分:5)

此代码从输入中读取符文。不需要强制转换,它就像迭代器一样:

package main

import (
    "bufio"
    "fmt"
    "strings"
)

func main() {
    in := `{"sample":"json string"}`

    s := bufio.NewScanner(strings.NewReader(in))
    s.Split(bufio.ScanRunes)

    for s.Scan() {
        fmt.Println(s.Text())
    }
}

答案 1 :(得分:5)

只需在循环中逐一阅读每个符文...... See example

编辑:为后代添加代码,以防链接死亡:

package main

import (
    "bufio"
    "fmt"
    "io"
    "log"
    "strings"
)

var text = `
The quick brown fox jumps over the lazy dog #1.
Быстрая коричневая лиса перепрыгнула через ленивую собаку.
`

func main() {
    r := bufio.NewReader(strings.NewReader(text))
    for {
        if c, sz, err := r.ReadRune(); err != nil {
            if err == io.EOF {
                break
            } else {
                log.Fatal(err)
            }
        } else {
            fmt.Printf("%q [%d]\n", string(c), sz)
        }
    }
}

答案 2 :(得分:1)

如果只是内存大小。在即将发布的版本中(很快),将会有json解码器的令牌样式增强功能: 你可以在这里看到它

https://tip.golang.org/pkg/encoding/json/#Decoder.Token