You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 00:40:30