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

如何在C#/PowerShell中处理7GB大CSV:移除字段内换行并拆分

处理带字段内换行的大型CSV拆分与换行符移除方案

C# 解决方案

使用.NET自带的TextFieldParser(来自Microsoft.VisualBasic程序集)流式解析CSV,它能自动识别带引号包裹的字段,正确处理字段内的换行符,同时避免一次性加载整个文件导致内存溢出。以下是完整实现:

using Microsoft.VisualBasic.FileIO;
using System.IO;
using System.Linq;

public void SplitAndCleanLargeCsv(string inputFilePath, string outputDirectory, int batchSize)
{
    Directory.CreateDirectory(outputDirectory);
    int recordCount = 0;
    int fileIndex = 0;
    StreamWriter currentWriter = null;
    string[] headers = null;

    try
    {
        using (TextFieldParser parser = new TextFieldParser(inputFilePath))
        {
            parser.TextFieldType = FieldType.Delimited;
            parser.SetDelimiters(",");
            parser.HasFieldsEnclosedInQuotes = true; // 核心配置:识别带引号的字段,处理内部换行
            parser.TrimWhiteSpace = false; // 保留字段原始格式,按需调整

            // 读取表头行
            headers = parser.ReadFields();
            if (headers == null) return;

            while (!parser.EndOfData)
            {
                try
                {
                    // 读取完整的一条记录(自动处理字段内换行)
                    string[] fields = parser.ReadFields();
                    if (fields == null) break;

                    // 移除每个字段内的换行符(替换为空格,可按需改为空字符串)
                    for (int i = 0; i < fields.Length; i++)
                    {
                        if (!string.IsNullOrEmpty(fields[i]))
                        {
                            fields[i] = fields[i].Replace("\r\n", " ").Replace("\n", " ").Replace("\r", " ");
                        }
                    }

                    // 每batchSize条记录新建一个输出文件
                    if (recordCount % batchSize == 0)
                    {
                        currentWriter?.Dispose();
                        string outputPath = Path.Combine(outputDirectory, $"output_{fileIndex}.csv");
                        currentWriter = new StreamWriter(outputPath);
                        // 写入转义后的表头(处理表头中的引号)
                        currentWriter.WriteLine(string.Join(",", headers.Select(h => $"\"{h.Replace("\"", "\"\"")}\"")));
                        fileIndex++;
                    }

                    // 写入转义后的记录,避免CSV格式错误
                    string line = string.Join(",", fields.Select(f => 
                        string.IsNullOrEmpty(f) ? "" : $"\"{f.Replace("\"", "\"\"")}\""));
                    currentWriter.WriteLine(line);
                    recordCount++;
                }
                catch (MalformedLineException ex)
                {
                    // 处理格式错误的行,可添加日志记录
                    System.Console.WriteLine($"跳过格式异常行:{ex.Message}");
                }
            }
        }
    }
    finally
    {
        currentWriter?.Dispose();
    }
}

注意事项

  • 需要引用Microsoft.VisualBasic程序集:.NET Framework可直接添加引用,.NET Core/.NET 5+可通过NuGet安装Microsoft.VisualBasic包
  • 换行符替换规则可根据需求调整,例如替换为""删除换行
  • 代码自动处理字段内的引号转义(用""表示单个"),保证输出CSV格式合法

PowerShell 解决方案

手动处理带引号字段的换行拼接,流式读写避免内存溢出,同时移除字段内的换行符:

$inputPath = "C:\largefile.csv"
$outputDir = "C:\split_csv_output"
$batchSize = 10000

# 创建输出目录
if (-not (Test-Path $outputDir)) {
    New-Item -ItemType Directory -Path $outputDir | Out-Null
}

$reader = New-Object System.IO.StreamReader($inputPath)
$header = $reader.ReadLine()
$recordCount = 0
$fileIndex = 0
$writer = $null

try {
    while ($line = $reader.ReadLine()) {
        # 拼接字段内换行的不完整记录:通过引号数量判断是否为完整行
        $quoteCount = ($line | Select-String '"' -AllMatches).Count
        while ($quoteCount % 2 -ne 0) {
            $nextLine = $reader.ReadLine()
            if (-not $nextLine) break
            $line += "`n$nextLine"
            $quoteCount += ($nextLine | Select-String '"' -AllMatches).Count
        }

        # 将单行记录转为对象
        $record = $line | ConvertFrom-Csv -Header ($header -split ',')

        # 移除每个字段内的换行符
        foreach ($prop in $record.PSObject.Properties) {
            if ($prop.Value -is [string]) {
                $prop.Value = $prop.Value -replace "`r`n|`n|`r", " "
            }
        }

        # 每batchSize条记录新建输出文件
        if ($recordCount % $batchSize -eq 0) {
            if ($writer) { $writer.Close(); $writer.Dispose() }
            $outputPath = Join-Path $outputDir "smallfile_$fileIndex.csv"
            $writer = New-Object System.IO.StreamWriter($outputPath)
            $writer.WriteLine($header)
            $fileIndex++
        }

        # 将处理后的记录转为CSV行并写入
        $csvLine = $record | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1
        $writer.WriteLine($csvLine)
        $recordCount++
    }
}
finally {
    # 释放资源
    if ($writer) { $writer.Close(); $writer.Dispose() }
    $reader.Close(); $reader.Dispose()
}

注意事项

  • 通过引号数量判断是否为完整记录,解决ReadLine拆分字段内换行的问题
  • 流式处理逐行读写,不会加载整个7GB文件到内存
  • 换行符替换可通过修改正则表达式调整规则

内容的提问来源于stack exchange,提问作者404

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:07:52