Go语言中的文件与IO:bufio 和 scanner

Go 标准库中的 bufio 包提供了带缓冲的读写功能,可以显著提高文件和数据处理效率。而 bufio.Scanner 则是读取文本文件中每一行的利器,常用于日志、配置等文本处理场景。


一、为什么使用 bufio

直接对文件进行 os.File.Read()os.File.Write() 操作是无缓冲的,每次调用都会进行系统调用,效率较低。

bufio 在内部使用内存缓冲区,减少与操作系统的交互,性能提升明显。


二、bufio.Reader:带缓冲的读取

示例:读取文件内容并逐行输出

scss 复制代码
file, err := os.Open("sample.txt")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

reader := bufio.NewReader(file)

for {
    line, err := reader.ReadString('\n')
    if err == io.EOF {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
    fmt.Print(line)
}

方法说明:

  • ReadString(delim byte):读到指定分隔符为止(如 \n)。
  • ReadBytes(delim byte):与 ReadString 类似,但返回字节切片。
  • ReadLine():低级函数,建议用 Scanner 替代。
  • Peek(n int):读取但不消费前 n 个字节。

三、bufio.Writer:带缓冲的写入

css 复制代码
file, _ := os.Create("output.txt")
defer file.Close()

writer := bufio.NewWriter(file)
writer.WriteString("Hello, buffered write!\n")
writer.Flush() // 必须显式刷新缓冲区

注意: 使用 bufio.Writer 写入数据后,需要调用 Flush() 将数据写入底层文件或网络连接,否则可能数据不会立即写入。


四、bufio.Scanner:按行或自定义分隔符扫描输入

1. 按行读取文本文件

css 复制代码
file, _ := os.Open("sample.txt")
defer file.Close()

scanner := bufio.NewScanner(file)
for scanner.Scan() {
    fmt.Println(scanner.Text())
}

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

2. 自定义分隔符(如按空格、逗号、段落分隔)

css 复制代码
scanner := bufio.NewScanner(strings.NewReader("go is simple. go is fast."))

// 自定义按单词分割
scanner.Split(bufio.ScanWords)

for scanner.Scan() {
    fmt.Println(scanner.Text())
}

常见分割器:

  • bufio.ScanLines(默认)
  • bufio.ScanWords
  • bufio.ScanBytes

五、Scanner 与大文件的关系

  • Scanner 默认缓冲区大小为 64K,如需处理超大行文本,可以通过 scanner.Buffer() 提高上限:
go 复制代码
scanner.Buffer(make([]byte, 1024), 10*1024*1024) // 提升最大支持到10MB

六、小结

类型 功能 适合场景
bufio.Reader 提供高效逐行或按字节读取 网络流、日志、长行文本等
bufio.Writer 高效写入并可缓冲 写文件、网络输出
bufio.Scanner 方便读取行、单词等小粒度内容 配置文件、日志文件、终端输入

七、建议实践练习

    1. 写一个程序,读取大文件并统计每一行的字符数。
    1. 模拟 tail -f,持续从文件末尾读取新增内容。
    1. 实现一个按单词频率排序的词频统计器。

相关推荐
Gogo8161 小时前
BigInt 与 Number 的爱恨情仇,为何大佬都劝你“能用 Number 就别用 BigInt”?
后端
fuquxiaoguang1 小时前
深入浅出:使用MDC构建SpringBoot全链路请求追踪系统
java·spring boot·后端·调用链分析
毕设源码_廖学姐2 小时前
计算机毕业设计springboot招聘系统网站 基于SpringBoot的在线人才对接平台 SpringBoot驱动的智能求职与招聘服务网
spring boot·后端·课程设计
mtngt113 小时前
AI DDD重构实践
go
野犬寒鸦3 小时前
从零起步学习并发编程 || 第六章:ReentrantLock与synchronized 的辨析及运用
java·服务器·数据库·后端·学习·算法
逍遥德4 小时前
如何学编程之01.理论篇.如何通过阅读代码来提高自己的编程能力?
前端·后端·程序人生·重构·软件构建·代码规范
MX_93594 小时前
Spring的bean工厂后处理器和Bean后处理器
java·后端·spring
程序员泠零澪回家种桔子5 小时前
Spring AI框架全方位详解
java·人工智能·后端·spring·ai·架构
源代码•宸6 小时前
大厂技术岗面试之谈薪资
经验分享·后端·面试·职场和发展·golang·大厂·职级水平的薪资
晚霞的不甘7 小时前
CANN 编译器深度解析:UB、L1 与 Global Memory 的协同调度机制
java·后端·spring·架构·音视频