
本文介绍使用go语言扫描结构化文本文件,识别并输出所有含重复16位“text”字段的完整行,避免单次扫描流耗尽问题,并推荐基于哈希映射的内存高效方案。
本文介绍使用go语言扫描结构化文本文件,识别并输出所有含重复16位“text”字段的完整行,避免单次扫描流耗尽问题,并推荐基于哈希映射的内存高效方案。
在处理如 store.txt 这类固定格式文件(每行形如 0000011234567890123456,前6位为索引、后16位为文本)时,目标是找出所有出现次数 ≥ 2 的16位 text 值,并完整打印其所在行。原始代码存在两个关键缺陷:一是嵌套 scanner.Scan() 导致内层循环读取至文件末尾(EOF),外层循环随即终止;二是用切片线性查找 contains 效率低(O(n²)),且未保存原始行内容,无法后续回溯打印。
✅ 正确思路应分两阶段:
-
首次遍历:提取每行的
text(即line[6:]),用map[string]int统计频次; -
二次遍历(或单遍缓存):再次读取文件,对每个
text判断频次 > 1,满足则打印整行。
以下是优化后的完整实现(单次打开、两次扫描,内存安全、逻辑清晰):
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
file, err := os.Open("store.txt")
if err != nil {
panic(err)
}
defer file.Close()
// 第一阶段:统计所有 text 的出现频次
counts := make(map[string]int)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if len(line) 1 的完整行
fmt.Println("Duplicate lines (text appears more than once):")
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if len(line) 1 {
fmt.Println(line)
}
}
if err := scanner.Err(); err != nil {
panic(err)
}
}
? 关键说明与注意事项:
-
避免流耗尽:使用
file.Seek(0, 0)重置读取位置,而非尝试嵌套扫描器——Go 的bufio.Scanner不支持重置,必须显式 seek。 -
边界安全:用
strings.TrimSpace和len(line) 防止越界 panic;<code>line[6:22]精确提取16位(非utf8.RuneCountInString,因输入保证为ASCII数字,字节长度即字符长度)。 -
性能优势:
map[string]int查找为 O(1),整体时间复杂度 O(n);相比切片contains的 O(n²),大数据量下提升显著。 -
扩展建议:若文件极大(无法两次加载),可改用单遍方案——缓存首次出现的行(
map[string][]string),第二次遇到重复时立即输出已缓存行 + 当前行;但需权衡内存占用。
该方案简洁、健壮、符合Go惯用法,适用于日志去重、数据校验等实际场景。










