Golang - 如何克服 bufio 的 Scan() 缓冲区限制?

Posted

技术标签:

【中文标题】Golang - 如何克服 bufio 的 Scan() 缓冲区限制?【英文标题】:Golang - How to overcome Scan() buffer limit from bufio? 【发布时间】:2016-10-04 18:20:54 【问题描述】:

我正在使用bufio 扫描仪的.Scan() 方法来读取文本文件行。但是,当我在文件行中达到一定大小时,扫描仪不再允许我读取,它只会返回一个空行。

我应该如何配置缓冲区以接收大量数据?

bigfile.txt 只是一个文件,其中一行中有许多整数,由空格分隔。例如,一行 40000 个整数。 (请注意,它适用于 10000 及以下的文件行,但不适用于 40000 的文件行)

234 544 765 45 34 67 67 87 98 43 [... n = 40000 ]

func main() 
    readInputFile("bigfile.txt")


func readInputFile(name string) 
    inFile, _ := os.Open(name)
    defer inFile.Close()

    scanner := bufio.NewScanner(inFile)

    for scanner.Scan() 
        line := scanner.Text()
        fmt.Printf(line)
    

【问题讨论】:

在您的for 循环之后添加对scanner.Err() 的调用,看看它会给您带来什么。也许那里有一些有用的东西? golang.org/pkg/bufio/#Scanner.Err 【参考方案1】:

根据documentation和对应的source code,默认Scanner使用容量为64K的内部缓冲区。在您的情况下,内部缓冲区不足以存储 40000 个整数。设置扫描仪调用Scan之前使用的缓冲区,即

scanner := bufio.NewScanner(inFile)

//adjust the capacity to your need (max characters in line)
const maxCapacity = 512*1024  
buf := make([]byte, maxCapacity)
scanner.Buffer(buf, maxCapacity)

【讨论】:

为什么缓冲区大小设置为512*1024? 仅作为示例。实际容量将取决于您的具体输入。【参考方案2】:

使用动态缓冲区大小的代码。获取文件大小并在扫描仪中使用

info, infoErr := file.Stat()
var maxSize int
scanner := bufio.NewScanner(file)
maxSize = int(info.Size())
buffer := make([]byte, 0, maxSize)
scanner.Buffer(buffer, maxSize)

为 JSON 添加更多字节 最大尺寸 = 最大尺寸 + 1 或者 最大尺寸 = 最大尺寸 + 10

【讨论】:

为什么“为 JSON 添加更多字节”?还有,为什么是“+1”或“+10”……你会如何决定?

以上是关于Golang - 如何克服 bufio 的 Scan() 缓冲区限制?的主要内容,如果未能解决你的问题,请参考以下文章

golang (*bufio.Reader)的读取方法

golang 中通过strings/bytes/bufio 等包实现相关IO

Golang逐行读取大文件性能对比

golang 缓冲区的终端输入

Go语言自学系列 | golang标准库bufio

GoLang几种读文件方式的比较