Как читать текстовый файл по строкам в Go, если некоторые строки достаточно длинны, чтобы вызвать ошибки "bufio.Scanner: token too long"?
У меня есть текстовый файл, где каждая строка представляет объект JSON. Я обрабатываю этот файл в Go с помощью простого цикла for
этого:
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)
}
Когда этот код достигает строки с особенно большой строкой JSON (~ 67kb), я получаю сообщение об ошибке "bufio.Scanner: токен слишком длинный".
Есть ли простой способ увеличить максимальный размер строки, читаемый NewScanner
? Или есть другой подход, который вы можете предпринять вообще, когда нужно читать строки, которые слишком велики для NewScanner
но, как известно, обычно не имеют небезопасного размера?
Ответы
Ответ 1
Из документов пакета:
Программы, которые нуждаются в большем контроле над обработкой ошибок или большими токенами или должны выполнять последовательное сканирование на считывателе, вместо этого должны использовать bufio.Reader.
Похоже, предпочтительным решением является bufio.Reader.ReadLine.
Ответ 2
Вы также можете сделать:
scanner := bufio.NewScanner(file)
buf := make([]byte, 0, 64*1024)
scanner.Buffer(buf, 1024*1024)
for scanner.Scan() {
// do your stuff
}
Второй аргумент для scanner.Buffer() устанавливает максимальный размер маркера. В приведенном выше примере вы сможете сканировать файл, если ни одна из строк не превышает 1 МБ.
Ответ 3
Вы, конечно же, не хотите, чтобы вы читали строки за строкой в первую очередь. Почему бы вам просто не сделать это:
d := json.NewDecoder(file)
for {
var ob whateverType
err := d.Decode(&ob)
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("Error decoding: %v", err)
}
// do stuff with "jsonObject"...
}