最初,您可能会在逐行读取文件并将进度保存在去。 bufio 包中的扫描仪不提供行号方法。但是,以下是潜在的解决方案:
bufio.Scanner 可以扩展以保持位置。实现一个分割函数,将输入分割成标记(行)并跟踪读取的字节。下面的示例使用内置 bufio.ScanLines() 作为基础,并使用提前返回值维护位置 (pos):
func withScanner(input io.ReadSeeker, start int64) error { if _, err := input.Seek(start, 0); err != nil { return err } scanner := bufio.NewScanner(input) pos := start scanLines := func(data []byte, atEOF bool) (advance int, token []byte, err error) { advance, token, err = bufio.ScanLines(data, atEOF) pos += int64(advance) return } scanner.Split(scanLines) for scanner.Scan() { fmt.Printf("Pos: %d, Scanned: %s\n", pos, scanner.Text()) } return scanner.Err() }
bufio.Reader 允许您使用 ReadBytes() 使用 'n' 作为分隔符来读取一行。下面的示例处理多个行终止符序列 (rn) 并将它们从读取行中剥离:
func withReader(input io.ReadSeeker, start int64) error { if _, err := input.Seek(start, 0); err != nil { return err } r := bufio.NewReader(input) pos := start for { data, err := r.ReadBytes('\n') pos += int64(len(data)) if err == nil || err == io.EOF { if len(data) > 0 && data[len(data)-1] == '\n' { data = data[:len(data)-1] } if len(data) > 0 && data[len(data)-1] == '\r' { data = data[:len(data)-1] } fmt.Printf("Pos: %d, Read: %s\n", pos, data) } if err != nil { if err != io.EOF { return err } break } } return nil }
要测试解决方案,您可以使用内容“firstrnsecondnthirdnfourth”作为具有干净启动(start = 0)和恢复位置(start = 14)的输入。输出将显示位置并读取行:
--SCANNER, start: 0 Pos: 7, Scanned: first Pos: 14, Scanned: second Pos: 20, Scanned: third Pos: 26, Scanned: fourth --READER, start: 0 Pos: 7, Read: first Pos: 14, Read: second Pos: 20, Read: third Pos: 26, Read: fourth --SCANNER, start: 14 Pos: 20, Scanned: third Pos: 26, Scanned: fourth --READER, start: 14 Pos: 20, Read: third Pos: 26, Read: fourth
以上是如何使用扫描仪读取 Go 中从特定行号开始的文件?的详细内容。更多信息请关注PHP中文网其他相关文章!