Go语言 为什么在重复使用布法罗之后,即使源代码没有被完全读取,使用相同读取器的新扫描仪也会导致EOF?

b09cbbtk  于 2023-08-01  发布在  Go
关注(0)|答案(1)|浏览(92)

我有一个包含以下内容的文件:

3
09:00 19:00
10
someText1
someText2
...

字符串
首先,我想阅读配置的前3行:

sourceFile, err := os.OpenFile(fileName, os.O_RDONLY, 0644)
cfg := ReadConfig(sourceFile)

func ReadConfig(r io.Reader) Config {
    scanner := bufio.NewScanner(r)
    var cfg Config
    for i := 0; i < 3 && scanner.Scan(); i++ {
        switch i {
        case 0:
            cfg.Parts, _ = strconv.Atoi(scanner.Text())
        case 1:
            timeParts := strings.Split(scanner.Text(), " ")
            cfg.Start, _ = time.Parse("15:04", timeParts[0])
            cfg.End, _ = time.Parse("15:04", timeParts[1])
        case 2:
            cfg.Val, _ = strconv.Atoi(scanner.Text())
        }
    }
    return cfg

}


它们被正常读取,现在在另一个函数中,我想读取其余的:

Read(ctx, sourceFile)

func Read(ctx context.Context, r io.Reader) error {
    scanner := bufio.NewScanner(r)
    for scanner.Scan() {
            event := parseEvent(scanner.Text())
    }
    return nil
}


但是不会发生读取,因为EOF会立即返回。为什么我只读了3行就发生了这种情况?

jrcvhitl

jrcvhitl1#

bufio.Scanner在内部使用缓冲区(源代码):

type Scanner struct {
    r            io.Reader
    split        SplitFunc
    maxTokenSize int
    token        []byte
    buf          []byte    // Buffer used as argument to split.
    //^^^^^^^^^^^^^^^^^
    start        int
    end          int
    err          error
    empties      int
    scanCalled   bool
    done         bool
}

字符串
初始缓冲区大小为4096(源代码):

const (
    startBufSize = 4096 // Size of initial allocation for buffer.
)


Scan的第一次调用从底层读取器(源代码)读取最多startBufSize字节。
您可以看到,尽管使用扫描程序只读取3行,但扫描程序可以将更多的字节读入其缓冲区。
bufio.Reader具有类似的行为。看这个问题:Multiple Arrow CSV Readers on same file returns null的数据。

相关问题