Golang中使用bufio.Scanner读取10GB大文件时遇到"token too long"错误

Golang中使用bufio.Scanner读取10GB大文件时遇到"token too long"错误 在读取一个10GB的大型文本文件时,每行都是长嵌套的JSON结构。 我使用以下代码读取内容:

scanner := bufio.NewScanner(file)
scanner.Scan()

遇到错误:bufio.Scanner: token too long

需要帮助解决此问题,或者提供替代的代码片段。

6 回复

你能展示给我们看产生这个错误的代码行吗?

更多关于Golang中使用bufio.Scanner读取10GB大文件时遇到"token too long"错误的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


谢谢。我也做了同样的事情。 ☀️ 🤫

你可以尝试使用 bufio.NewReader(file) 然后调用 ReadString("/n")

bufio.NewReader(file)
ReadString("/n")

你好

使用 https://golang.org/pkg/bufio/#Scanner.Buffer 设置足够大的缓冲区用于读取。

感谢,但这种方式需要对代码进行更多修改,而不仅仅是更改缓冲区限制。 :sunny: :shushing_face:

在Golang中使用bufio.Scanner读取大文件时遇到"token too long"错误是因为默认的缓冲区大小限制。bufio.Scanner的默认最大令牌大小为bufio.MaxScanTokenSize(64KB),当单行超过这个限制时就会报错。

以下是几种解决方案:

方案1:自定义缓冲区大小

package main

import (
    "bufio"
    "bytes"
    "os"
)

func main() {
    file, err := os.Open("large_file.json")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    
    // 自定义缓冲区大小(例如10MB)
    buf := make([]byte, 0, 64*1024)
    scanner.Buffer(buf, 10*1024*1024) // 初始大小64KB,最大10MB

    for scanner.Scan() {
        line := scanner.Text()
        // 处理每一行
        _ = line
    }

    if err := scanner.Err(); err != nil {
        panic(err)
    }
}

方案2:使用bufio.Reader逐块读取

package main

import (
    "bufio"
    "io"
    "os"
)

func readLargeFile(filename string) error {
    file, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    reader := bufio.NewReader(file)
    buf := make([]byte, 1024*1024) // 1MB缓冲区

    for {
        n, err := reader.Read(buf)
        if err != nil && err != io.EOF {
            return err
        }
        if n == 0 {
            break
        }

        // 处理读取的数据块
        chunk := buf[:n]
        _ = chunk
    }

    return nil
}

方案3:使用ioutil.ReadFile(适用于可装入内存的文件)

package main

import (
    "io/ioutil"
    "os"
)

func readEntireFile(filename string) error {
    data, err := ioutil.ReadFile(filename)
    if err != nil {
        return err
    }
    
    // 整个文件内容在data中
    _ = data
    return nil
}

方案4:逐字符读取处理JSON行

package main

import (
    "bufio"
    "io"
    "os"
)

func readJSONLines(filename string) error {
    file, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    reader := bufio.NewReader(file)
    var line []byte
    
    for {
        chunk, isPrefix, err := reader.ReadLine()
        if err == io.EOF {
            break
        }
        if err != nil {
            return err
        }
        
        line = append(line, chunk...)
        if !isPrefix {
            // 完整的一行JSON
            jsonLine := string(line)
            _ = jsonLine
            
            // 重置line
            line = line[:0]
        }
    }
    
    return nil
}

对于10GB的JSON文件,推荐使用方案1或方案2。方案1通过增加缓冲区大小来处理长行,方案2则提供了更细粒度的控制,适合处理超大型文件。根据你的JSON行平均长度选择合适的缓冲区大小。

回到顶部