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

我发现this example用于遍历字符串中的单词,并且bufio包中的the ScanRunes函数看起来可以一次返回一个字符。我也有bufio的ReadRune函数可以正常工作,但是感觉很沉重。

编辑

我比较了3种方法。全部使用循环从bufio.Reader或bufio.Scanner中提取内容。

  • 使用.ReadRune上的bufio.Reader循环读取 rune 。检查从对.ReadRune的调用是否有错误。
  • 在扫描仪上调用bufio.Scanner后,从.Split(bufio.ScanRunes)中读取字节。在每次迭代中分别调用.Scan .Bytes ,检查.Scan调用是否有错误。
  • 与#2相同,但使用 bufio.Scanner .Text而不是字节读取文本。我没有使用string([]runes)来连接一小段 rune ,而是使用strings.Join([]strings, "")来连接一串字符串,以形成最终的文本 Blob 。

  • 在23 MB的json文件上运行10次的时间是:
  • 0.65 s
  • 2.40 s
  • 0.97 s

  • 所以ReadRune看起来还算不错。由于每个 rune 都是通过1次操作(.ReadRune)而不是2次(.Scan.Bytes)提取的,因此它也导致了较小的详细调用。

    最佳答案

    只需在循环中逐一读取每个 rune ... 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)
            }
        }
    }
    

    10-07 13:09