0

0

Golang读取文本文件按行处理示例

P粉602998670

P粉602998670

发布时间:2026-01-07 17:29:54

|

903人浏览过

|

来源于php中文网

原创

bufio.Scanner 是 Go 按行读取文本的首选,自动处理换行符、内存可控、默认单行上限 64KB;避免 os.ReadFile+strings.Split(易 OOM)和 bufio.Reader.ReadString(易漏末行);需检查 scanner.Err() 而非仅 io.EOF;超长行可调用 scanner.Buffer 自定义缓冲区。

golang读取文本文件按行处理示例

bufio.Scanner 按行读取最稳妥

绝大多数场景下,bufio.Scanner 是 Go 里按行处理文本文件的首选。它自动处理换行符(\n\r\n),内存占用可控,且默认单行上限 64KB —— 对普通日志或配置文件完全够用。

常见错误是直接用 os.ReadFile + strings.Split 一次性加载整个文件,大文件容易 OOM;或者用 bufio.Reader.ReadString('\n') 手动处理,结果漏掉最后一行(没换行符时返回 io.EOF 但不报错)。

  • scanner.Scan() 循环,每次调用后用 scanner.Text() 获取当前行(不含换行符)
  • 检查 scanner.Err() 判断是否因 I/O 错误提前退出,别只看 io.EOF
  • 若需处理超长行(如某些导出数据),提前调用 scanner.Buffer(make([]byte, 0), 1 扩容缓冲区
file, err := os.Open("data.txt")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

scanner := bufio.NewScanner(file)
for scanner.Scan() {
    line := scanner.Text()
    // 处理每一行,例如:strings.TrimSpace(line)
    fmt.Println(line)
}
if err := scanner.Err(); err != nil {
    log.Fatal(err)
}

bufio.Reader.ReadLine() 适合需要原始字节或控制换行符的场景

bufio.Reader.ReadLine() 返回 []byte 和一个布尔值,表示该行是否被截断(超过缓冲区长度)。它不自动去掉换行符,也不合并 \r\n,适合你明确要保留原始换行格式、或后续做二进制解析的情况。

注意:它返回的是切片,指向底层缓冲区,如果要长期保存某一行内容,必须用 append([]byte{}, line...) 复制一份,否则下一次调用会覆盖。

Typeface
Typeface

AI创意内容创作助手

下载
  • 返回的 isPrefixtrue 表示行太长被截断,需循环读取直到 isPrefix == false
  • 遇到空行时返回空切片 []byte{},不是 nil,别用 == nil 判空
  • Scanner 多一层控制,但也多一层出错可能 —— 比如忘记处理 isPrefix

按行读取时忽略 BOM 是个高频坑

Windows 上用记事本保存的 UTF-8 文件常带 BOM(0xEF 0xBB 0xBF),bufio.Scanner 不会自动跳过它,第一行开头会出现乱码字符。这不是编码错误,而是字节被当作文本内容读进来了。

  • 打开文件后,先用 bytes.HasPrefix 检查前三个字节是否为 BOM,是则用 io.MultiReader 跳过
  • 更简单的方法:用 golang.org/x/text/encoding/unicode 包的 UTF8.NewDecoder().Bytes() 预处理整行(但会失去流式优势)
  • 如果确定文件来源固定,可在写入端统一禁用 BOM(比如 VS Code 设置 "files.encoding": "utf8" 并关掉 "files.autoGuessEncoding"

大文件分块读取 + 行边界对齐需手动处理

当文件上百 MB 以上,且每行极短(如 CSV 记录),Scanner 仍够用;但如果单行本身长达几 MB,或你需要严格控制每次系统调用大小(比如限流读取网络响应体),就得绕过 Scanner,用 bufio.Reader.Read() 分块读,再自己找换行符位置。

这时关键难点是:换行符可能被切在两块之间。例如块末尾是 "hello\r",下一块开头是 "\nworld"。必须把上一块末尾的 \r 和下一块开头的 \n 拼起来识别为完整行尾。

  • 缓存未完成的行前缀(尤其以 \r 结尾时),下一轮读取后拼接再判断
  • 别用 bytes.IndexByte(buf, '\n') 简单切分 —— 它无法处理 \r\n 组合
  • 实际项目中,优先考虑用现成库如 github.com/apache/arrow/go/arrow/ipc(针对结构化数据)或 encoding/csv(针对 CSV),它们内部已处理好边界问题
BOM 和跨块换行符对齐这两点,初学者常以为“读到换行就完事”,结果线上跑几天才发现第一行或某几行内容异常 —— 它们不会报错,只会静默出错。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

177

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

226

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

336

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

208

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

388

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

194

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

189

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

191

2025.06.17

java学习网站推荐汇总
java学习网站推荐汇总

本专题整合了java学习网站相关内容,阅读专题下面的文章了解更多详细内容。

6

2026.01.08

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.5万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号