如何在Go中逐个字符地读取文件

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

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

编辑

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

  1. 使用.ReadRuneon a循环读取符文bufio.Reader。检查调用中的错误.ReadRune

  2. bufio.Scanner在调用.Split(bufio.ScanRunes)扫描器后从 a 读取字节。调用.Scan.Bytes在每次迭代,检查.Scan调用错误。

  3. 与#2 相同,但bufio.Scanner使用.Text.从 a而不是字节读取文本。string([]runes)我没有加入一片符文,而是加入了一片字符串strings.Join([]strings, "")以形成最终的文本块。

在 23 MB json 文件上各运行 10 次的时间为:

  1. 0.65 s

  2. 2.40 s

  3. 0.97 s

所以看起来ReadRune毕竟还不错。它还导致更小、更简洁的调用,因为每个符文都是在 1 个操作 ( .ReadRune) 而不是 2 个 (.Scan.Bytes) 中获取的。


波斯汪
浏览 269回答 3
3回答

MMTTMM

只需在循环中一个一个地读取每个符文...参见示例package mainimport (    "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)        }    }}

千巷猫影

此代码从输入读取符文。不需要强制转换,它类似于迭代器:package mainimport (    "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())    }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go