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

8次阅读

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

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

go 中逐行读取整数文本文件时,一个典型陷阱是:使用 bufio.Reader.ReadString(‘n’) 会将换行符 n(或 windows 下的 rn)包含在返回字符串。正如问题中所观察到的——lineStr 长度为 4 而非 2,且内容实际为 “10n”(UTF-8 编码下 ‘n’ 占 1 字节,’1′ 和 ‘0’ 各占 1 字节,共 3 字节;若输出显示长度为 4,很可能文件为 CRLF 换行,即 “10rn”),这导致 strconv.Atoi(“10n”) 或 strconv.ParseUint(“10n”, 0, 64) 无法识别为有效整数,返回 0 和错误。

虽然可通过 strings.TrimSpace(line) 手动清理空白符(包括 n, r, t, 空格等),但更推荐、更符合 Go 习惯的方式是使用 bufio.Scanner:

package main  import (     "bufio"     "fmt"     "os"     "strconv" )  func main() {     file, err := os.Open("input.txt")     if err != nil {         panic(err)     }     defer file.Close()      scanner := bufio.NewScanner(file)     for scanner.Scan() {         line := scanner.Text() // ✅ 自动去除行尾换行符,不包含 n 或 rn         num, err := strconv.Atoi(line)         if err != nil {             fmt.Printf("警告:跳过无效行 '%s' — %vn", line, err)             continue         }         fmt.Printf("解析成功:'%s' → %dn", line, num)     }      if err := scanner.Err(); err != nil {         panic(fmt.Sprintf("读取文件时出错:%v", err))     } }

关键优势

  • scanner.Text() 返回的字符串已自动剥离行终止符(n、rn),无需额外 Trim;
  • 内部按行缓冲,内存友好,适合大文件;
  • 错误处理清晰:scanner.Err() 可捕获 I/O 错误,strconv.Atoi 的错误则用于校验数据格式。

⚠️ 注意事项

  • bufio.Scanner 默认单行最大长度为 64KB(bufio.MaxScanTokenSize),若需读取超长行,请提前设置:
    scanner := bufio.NewScanner(file) scanner.Buffer(make([]byte, 64*1024), 1<<20) // 最大支持 1MB 行
  • 始终检查 strconv.Atoi 的错误返回,避免静默失败(如空行、字母混入等);
  • 不要忽略 scanner.Err() —— 它是检测读取过程中底层 I/O 错误(如磁盘损坏、权限不足)的唯一途径。

总结:避免直接使用 ReadString('n') 处理行数据;优先选用 bufio.Scanner,它专为“按行读取”设计,语义清晰、健壮性强、符合 Go 生态最佳实践。

text=ZqhQzanResources