Go语言按行数分割大CSV/TXT文件问题求助(附代码)
大型CSV文件按行数分割的正确实现
原代码的核心问题
- 错误复用
file变量,覆盖了输入文件句柄,导致输入文件管理混乱、提前异常关闭 - 循环内使用
defer,延迟操作会在整个main函数结束才执行,造成文件未及时关闭、数据未刷入磁盘 - 每次写入都把积累的所有行重复输出,导致文件内容冗余重复
- 未处理最后一批不足指定行数的数据,会丢失剩余内容
可靠实现方案(CSV专用)
以下代码用csv.Reader/csv.Writer确保CSV格式正确性(比如处理字段含换行、引号的场景),同时保证逻辑清晰:
package main import ( "encoding/csv" "fmt" "log" "os" ) const ( inputFile = "abc.csv" linesPerFile = 50 ) func main() { // 打开输入CSV文件 inFile, err := os.Open(inputFile) if err != nil { log.Fatalf("打开输入文件失败: %v", err) } defer inFile.Close() reader := csv.NewReader(inFile) // 读取表头(若CSV无表头,可删除这段代码) header, err := reader.Read() if err != nil { log.Fatalf("读取表头失败: %v", err) } fileCount := 1 currentLineCount := 0 var outFile *os.File var writer *csv.Writer // 循环读取每一行数据 for { record, err := reader.Read() if err != nil { break // 读取完毕或出错,退出循环 } // 需创建新文件的场景:当前文件行数满了,或是第一次写入 if currentLineCount == 0 { // 关闭上一个文件(如果存在) if outFile != nil { writer.Flush() outFile.Close() } // 创建新输出文件 outFileName := fmt.Sprintf("abc_%d.csv", fileCount) outFile, err = os.Create(outFileName) if err != nil { log.Fatalf("创建文件%s失败: %v", outFileName, err) } fmt.Printf("创建文件: %s\n", outFileName) writer = csv.NewWriter(outFile) // 写入表头到新文件(无表头则删除此行) if err := writer.Write(header); err != nil { log.Fatalf("写入表头失败: %v", err) } fileCount++ } // 写入当前数据行 if err := writer.Write(record); err != nil { log.Fatalf("写入数据行失败: %v", err) } currentLineCount++ // 行数达标,重置计数准备切换文件 if currentLineCount >= linesPerFile { currentLineCount = 0 } } // 处理最后一个文件的剩余数据 if outFile != nil { writer.Flush() outFile.Close() } // 检查读取过程中的错误 if err := reader.Err(); err != nil { log.Fatalf("读取CSV出错: %v", err) } }
纯文本文件分割方案(TXT专用)
如果处理的是纯文本文件,可替换为bufio工具,逻辑类似:
package main import ( "bufio" "fmt" "log" "os" ) const ( inputFile = "abc.txt" linesPerFile = 50 ) func main() { inFile, err := os.Open(inputFile) if err != nil { log.Fatalf("打开输入文件失败: %v", err) } defer inFile.Close() scanner := bufio.NewScanner(inFile) fileCount := 1 currentLineCount := 0 var outFile *os.File var writer *bufio.Writer for scanner.Scan() { line := scanner.Text() if currentLineCount == 0 { if outFile != nil { writer.Flush() outFile.Close() } outFileName := fmt.Sprintf("abc_%d.txt", fileCount) outFile, err = os.Create(outFileName) if err != nil { log.Fatalf("创建文件%s失败: %v", outFileName, err) } fmt.Printf("创建文件: %s\n", outFileName) writer = bufio.NewWriter(outFile) fileCount++ } _, err := writer.WriteString(line + "\n") if err != nil { log.Fatalf("写入行失败: %v", err) } currentLineCount++ if currentLineCount >= linesPerFile { currentLineCount = 0 } } if outFile != nil { writer.Flush() outFile.Close() } if err := scanner.Err(); err != nil { log.Fatalf("读取文件出错: %v", err) } }
内容的提问来源于stack exchange,提问作者Clement
相关产品推荐
相关产品推荐

