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

大文本文件笛卡尔乘积生成方案及C#代码性能优化咨询

性能问题根源

你现有代码的性能瓶颈非常明确,完全是不必要的重复IO操作导致的:

  • 重复读取File1:每处理1条File2的记录就打开读取一次20MB的File1,6000次循环累计产生120GB的重复读磁盘开销,属于完全无意义的资源浪费
  • 频繁控制台输出:循环内每次都调用Console.WriteLine,大量IO等待会严重拖慢执行速度
  • 字符串编解码冗余:用StreamReader.ReadToEnd把字节流转成字符串再写入,多了两次编解码和内存拷贝开销
  • 缓冲区未优化:默认的流缓冲区太小,写入150GB大文件会触发过多的系统级IO调用
  • 若输入输出路径是网络共享路径,网络IO的延迟会进一步放大以上所有问题
优化方案

核心优化逻辑

  • 预加载File1到内存:20MB体积极小,一次性读取为字节数组留存,全程只需要读1次File1
  • 移除循环内高频控制台输出,仅保留必要的低频率进度提示即可
  • 直接用字节流写入,跳过字符串编解码步骤
  • 调大输出流的缓冲区到1MB以上,减少系统IO调用次数
  • 条件允许的话,先把输入文件复制到本地磁盘处理,完成后再传到目标网络路径

优化后代码示例

using System;
using System.IO;
using System.Linq;
using System.Text;

class FileMergeTool
{
    // 提前指定文件编码,根据你实际文件的编码调整,比如Encoding.GetEncoding("GBK")或者Encoding.UTF8
    private static readonly Encoding FileEncoding = Encoding.UTF8;
    // 输出缓冲区大小设为2MB,大幅减少IO次数
    private const int OutputBufferSize = 2 * 1024 * 1024;

    static void Main(string[] args)
    {
        DirectoryInfo di = new DirectoryInfo(@"\\InputPath");
        var transmitFiles = di.GetFiles().Where(file => file.FullName.Contains("TRANSMIT_MASS")).ToArray();
        string targetDate = DateTime.Now.AddDays(1).ToString("MMddyyyy");

        foreach (FileInfo f in transmitFiles)
        {
            string[] tokens = f.Name.Split('_');
            if (tokens[2] != targetDate) continue;

            string publishId = tokens[0];
            string outputPath = Path.Combine(@"\\OutputPath", $"{publishId}.txt");
            string file1Path = f.FullName;
            
            // 查找File2(SUBS门店文件)
            string storeFilePath = di.GetFiles()
                .Single(file => file.Name.StartsWith(publishId) && file.Name.Contains("SUBS"))
                .FullName;

            // 预加载File1全部内容到字节数组,全程仅读一次
            byte[] file1Bytes = File.ReadAllBytes(file1Path);
            byte[] newLineBytes = FileEncoding.GetBytes(Environment.NewLine);
            int processedCount = 0;

            // 写入输出文件
            using (var outputFs = new FileStream(outputPath, FileMode.Create, FileAccess.Write, FileShare.None, OutputBufferSize))
            using (var storeReader = new StreamReader(storeFilePath, FileEncoding))
            {
                string storeNumber;
                while ((storeNumber = storeReader.ReadLine()) != null)
                {
                    if (storeNumber.Length <= 5) continue;
                    
                    // 写入当前门店编号行
                    byte[] storeBytes = FileEncoding.GetBytes(storeNumber);
                    outputFs.Write(storeBytes, 0, storeBytes.Length);
                    outputFs.Write(newLineBytes, 0, newLineBytes.Length);
                    
                    // 直接写入预加载的File1内容,不需要重复读磁盘
                    outputFs.Write(file1Bytes, 0, file1Bytes.Length);
                    
                    // 每处理1000条打一次进度,减少输出开销
                    if (++processedCount % 1000 == 0)
                    {
                        Console.WriteLine($"已处理{processedCount}条门店记录");
                    }
                }
            }
            Console.WriteLine($"文件{publishId}.txt处理完成,共写入{processedCount}条门店数据");
        }
    }
}
补充说明
  • 不需要更换技术栈,C#完全可以满足需求,打包成Windows服务运行也没有任何问题
  • 如果服务器磁盘是SSD,优化后写入150GB文件耗时应该在10分钟以内,就算是机械硬盘也不会超过半小时
  • 如果必须用网络路径读写,可以在服务器上开启SMB3多通道优化,能显著提升网络文件读写速度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 11:54:03