17370845950

Go语言中逐行读取文本文件并解析整数的正确方法

本文详解如何在go中安全、高效地逐行读取含整数的文本文件,解决因换行符残留导致 `strconv.atoi` 解析失败的常见问题,并推荐使用 `bufio.scanner` 替代 `readstring`。

在Go中逐行读取整数文本文件时,一个典型误区是直接使用 bufio.Reader.ReadString('\n')——该方法会将换行符 \n(或 \r\n)一并包含在返回字符串中。例如,文件中写有 10 后跟换行,ReadString('\n') 实际返回的是 "10\n"(长度为3,若含回车则为4),而非干净的 "10"。这正是你观察到 len(lineStr) == 4 且 strconv.Atoi("

10\n") 返回 0 的根本原因:Atoi 和 ParseUint 均要求输入为纯数字字符串,遇到尾部空白或控制字符即解析失败。

✅ 正确做法是使用 bufio.Scanner,它专为按行读取设计,默认以 \n 为分隔符,且自动去除行尾换行符,返回纯净的 string:

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
)

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

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        line := scanner.Text() // ✅ 自动去除 \n,line = "10", not "10\n"
        if num, err := strconv.Atoi(line); err == nil {
            fmt.Printf("Parsed: %s → %d\n", line, num)
        } else {
            fmt.Printf("Failed to parse '%s': %v\n", line, err)
        }
    }

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

⚠️ 注意事项:

  • 永远检查错误:scanner.Err() 应在循环后显式调用,捕获扫描过程中的 I/O 错误;
  • 空行与空白处理:若文件可能含空行或首尾空格,建议先 strings.TrimSpace(line) 再解析;
  • 大文件性能:Scanner 默认缓冲区为64KB,对超大文件可调用 scanner.Buffer(make([]byte, 64*1024), 1
  • 替代方案(需手动清理):若坚持用 ReadString,务必用 strings.TrimSuffix(line, "\n") 或 strings.TrimSpace(line) 清理后再解析。

总结:bufio.Scanner 是Go标准库中读取文本行的首选工具——语义清晰、开箱即用、自动处理换行边界。避免手动处理分隔符带来的隐式污染,让整数解析回归简洁与健壮。