
本文介绍使用Go语言扫描结构化文本文件,识别并打印所有包含相同16位text字段的完整行,重点解决单次扫描流不可重入、重复逻辑失效等问题,并提供内存友好、可扩展的哈希映射实现方案。
本文介绍使用go语言扫描结构化文本文件,识别并打印所有包含相同16位`text`字段的完整行,重点解决单次扫描流不可重入、重复逻辑失效等问题,并提供内存友好、可扩展的哈希映射实现方案。
在处理如 store.txt 这类固定格式的日志或索引文件时(每行形如 000123123456789012,前6位为index,后16位为text),目标是找出所有具有重复text值的完整行——而非仅去重打印text本身。原始代码存在两个关键缺陷:一是嵌套 scanner.Scan() 导致内部循环耗尽输入流,使外层循环提前终止(EOF);二是用切片线性搜索 contains 效率低(O(n²)),且未保存原始行内容,无法回溯打印。
✅ 正确思路:两阶段处理 + 哈希映射
我们应分两步完成:
-
第一遍扫描:提取每行的
text(即line[6:]),统计其出现频次; -
第二遍扫描(或缓存行):再次读取文件,对每个
text查表,若频次 > 1,则输出整行。
但更优雅的方式是单遍扫描 + 行缓存:用 map[string][]string 记录每个 text 对应的所有完整行(保留原始格式),最后遍历 map 输出所有长度 ≥ 2 的条目:
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
file, err := os.Open("store.txt")
if err != nil {
panic(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
// text → []fullLine
duplicateMap := make(map[string][]string)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
// 跳过空行或格式异常行
if len(line) 1 {
fmt.Printf("\nText '%s' appears %d times:\n", text, len(lines))
for _, l := range lines {
fmt.Println(" ", l)
}
}
}
}
⚠️ 注意事项与优化建议
-
边界安全:使用
strings.TrimSpace和显式长度校验(len(line) >= 22)避免 panic; -
性能:
map[string][]string查找为 O(1),整体时间复杂度 O(n),远优于原方案的 O(n²); - 内存权衡:若文件极大(GB级),可改用两次扫描(第一次统计频次,第二次边读边查频次表并打印),避免全量缓存;
-
扩展性:如需支持大小写不敏感或正则匹配,可将
text预处理(如strings.ToLower)后再存入 map; -
错误处理:生产环境务必检查
os.Open和scanner.Err(),不可忽略错误。
该方案简洁、健壮、符合 Go 的惯用风格,既解决了原始逻辑的流耗尽问题,又以空间换时间提升了可维护性与执行效率。










