当一些行长到足以导致"bufio.Scanner:token too long"错误时,如何在Go中逐行读取文本文件?

Ste*_*ins 17 go

我有一个文本文件,其中每一行代表一个JSON对象.我正在使用这样的简单for循环在Go中处理此文件:

scanner := bufio.NewScanner(file)
for scanner.Scan() {
   jsonBytes = scanner.Bytes()
   var jsonObject interface{}
   err := json.Unmarshal(jsonBytes, &jsonObject)

   // do stuff with "jsonObject"...

}
if err := scanner.Err(); err != nil {
   log.Fatal(err)
}
Run Code Online (Sandbox Code Playgroud)

当此代码到达具有特别大的JSON字符串(~67kb)的行时,我收到错误消息"bufio.Scanner:token too long".

是否有一种简单的方法可以增加可读的最大行数NewScanner?或者是否有另一种方法可以完全采取,当需要读取太大NewScanner但不知道通常不安全的线路?

Pet*_*ley 18

包文档:

需要更多控制错误处理或大型令牌或必须在读取器上运行顺序扫描的程序应该使用bufio.Reader.

看起来首选的解决方案是bufio.Reader.ReadLine.

  • 谢谢!对于那些在这个问题上磕磕绊绊的人,我使用这个SO问题中的代码作为起点:http://stackoverflow.com/questions/6141604/go-readline-string. (5认同)

小智 15

你也可以这样做:

scanner := bufio.NewScanner(file)
buf := make([]byte, 0, 64*1024)
scanner.Buffer(buf, 1024*1024)
for scanner.Scan() {
    // do your stuff
}
Run Code Online (Sandbox Code Playgroud)

scanner.Buffer()的第二个参数设置最大令牌大小.在上面的示例中,只要没有任何行大于1MB,您就可以扫描文件.

  • 如果一行比缓冲区长,您还可以处理 `scanner.Err() == bufio.ErrTooLong`。 (3认同)
  • 我很确定 `buf := make([]byte, 0, 64*1024)` 行正在设置缓冲区的默认值,然后 `1024*024` 正在设置 _max_ 值。我不确定默认值较低有什么好处,但我认为它对内存使用和速度有益?无论如何,这对我来说非常有用。`ReadLine` 可能是“首选”,但这对于我已经使用扫描仪并遇到此问题的代码来说是一个简单的修复。 (2认同)