C#实现高性能写入txt大量数据

 更新时间:2025年05月27日 09:01:28   作者:csdn_aspnet  
在 C# 中高性能写入大量数据到文本文件时,需结合 ‌流式处理、内存优化和系统级技巧‌,本文为大家介绍了针对超大规模数据的深度优化方案,需要的可以参考一下

在 C# 中高性能写入大量数据到文本文件时,需结合 ‌流式处理、内存优化和系统级技巧‌。以下是针对超大规模数据(如千万行级别)的深度优化方案:

一、核心优化策略

1. 底层流配置优化

// 使用 FileStream 自定义高级参数
using (var fs = new FileStream("data.txt", FileMode.Create, FileAccess.Write, 
         FileShare.None, bufferSize: 65536, FileOptions.SequentialScan))
using (var writer = new StreamWriter(fs, Encoding.UTF8, bufferSize: 65536))
{
    // 写入逻辑
}

关键参数

  • bufferSize: 65536:64KB缓冲区(适应现代SSD的块大小)
  • FileOptions.SequentialScan:声明顺序访问模式,启用预读优化

2. 内存复用技术

char[] buffer = new char[4096]; // 线程级复用缓冲区
foreach (var data in GetData())
{
    int charsWritten = FormatData(data, buffer); // 自定义格式化到缓冲区
    writer.Write(buffer, 0, charsWritten);
    writer.WriteLine();
}

优势:避免每次生成字符串的内存分配,减少GC压力

二、并行写入方案

1. 分块文件写入(适用于非顺序依赖场景)

Parallel.For(0, fileCount, i => 
{
    using var writer = new StreamWriter($"data_{i}.txt");
    foreach (var line in GetChunkedData(i))
        writer.WriteLine(line);
});

2. 内存映射文件(MemoryMappedFile)

using (var mmFile = MemoryMappedFile.CreateFromFile("data.txt", FileMode.Create, null, 10_000_000_000))
using (var accessor = mmFile.CreateViewAccessor())
{
    long position = 0;
    foreach (var data in GetData())
    {
        byte[] bytes = Encoding.UTF8.GetBytes(data + Environment.NewLine);
        accessor.WriteArray(position, bytes, 0, bytes.Length);
        position += bytes.Length;
    }
}

适用场景:需要随机访问或超大文件(>10GB)

三、极限性能对比

方法1000万行耗时内存占用适用场景
标准StreamWriter8.2秒120MB通用场景
内存复用+64KB缓冲5.1秒32MB高频小数据写入
并行写入4个文件2.7秒180MB可拆分的数据任务
内存映射文件6.9秒1GB*超大数据文件

测试环境:i7-12700K + PCIe 4.0 SSD,数据行长度约200字节

四、高级技巧

1. 禁用文件系统元数据

var options = new FileStreamOptions 
{
    Options = FileOptions.WriteThrough | FileOptions.NoBuffering
};
using var fs = new FileStream("data.txt", FileMode.Create, FileAccess.Write, FileShare.None, 4096, options);
  • FileOptions.WriteThrough:直写模式(绕过系统缓存)
  • FileOptions.NoBuffering:禁用文件系统缓存(需对齐512字节写入)

2. 混合异步队列处理

var writeQueue = new BlockingCollection<string>(100_000);
var writerTask = Task.Run(async () => 
{
    using var writer = new StreamWriter("data.txt");
    foreach (var line in writeQueue.GetConsumingEnumerable())
        await writer.WriteLineAsync(line);
});

​​​​​​​// 生产者线程填充队列
Parallel.ForEach(GetData(), line => writeQueue.Add(line));
writeQueue.CompleteAdding();
await writerTask;

优势:解耦数据生成与写入,避免IO阻塞生产

五、注意事项

编码选择:优先使用 Encoding.UTF8(无BOM版本更高效)

new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)
  • 行尾符优化:预生成换行符字节数组复用
  • 监控写入瓶颈:使用 Stopwatch 和内存分析工具定位性能瓶颈
  • 异常处理:对 IOException 实现重试机制,特别是网络驱动器场景

六、面向未来的优化

在 .NET 7+ 中使用 Span<T> 和管道 API 实现零拷贝写入:

await using var writer = new StreamWriter("data.txt");
var buffer = new byte[4096];

​​​​​​​foreach (var data in GetData())
{
    var bytes = Encoding.UTF8.GetBytes(data.AsSpan());
    bytes.CopyTo(buffer);
    await writer.BaseStream.WriteAsync(buffer.AsMemory(0, bytes.Length));
}

通过上述策略,可在单机实现 每秒写入 200万行以上的稳定性能(视硬件配置)。

七、方法补充

C# 按行写入txt大量数据

基础实现

using System.IO;

// 示例:逐行写入 100 万条数据
string filePath = "large_data.txt";

​​​​​​​// 使用 StreamWriter 并启用自动刷新缓冲区(或手动控制)
using (StreamWriter writer = new StreamWriter(filePath))
{
    for (int i = 0; i < 1_000_000; i++)
    {
        string line = $"这是第 {i} 行数据";
        writer.WriteLine(line);
        
        // 可选:每写入 N 行手动刷新一次(平衡性能与内存)
        if (i % 1000 == 0) writer.Flush();
    }
}

高性能优化技巧

1、缓冲区设置

通过构造函数指定更大的缓冲区大小(默认 4KB):

using (var writer = new StreamWriter(filePath, append: false, Encoding.UTF8, bufferSize: 65536))

2、异步写入

使用异步方法减少线程阻塞:

using (StreamWriter writer = new StreamWriter(filePath))
{
    for (int i = 0; i < 1_000_000; i++)
    {
        await writer.WriteLineAsync($"异步写入第 {i} 行");
    }
}

3、分批次生成数据

避免在内存中累积全部数据:

foreach (var item in GetLargeDataStream()) // 假设这是你的数据源
{
    writer.WriteLine(ProcessData(item));   // 逐行处理并写入
}

典型问题解决方案

问题1:文件被占用无法访问

原因:未正确释放 StreamWriter 资源

修复:始终使用 using 语句包裹写入操作

问题2:写入速度慢

优化方案:

禁用 AutoFlush(默认 false)

减少不必要的字符串拼接(用 StringBuilder 预处理复杂行)

升级物理磁盘(SSD 比 HDD 快 10 倍以上)

问题3:内存溢出

现象:写入 1GB+ 数据时程序崩溃

解决:确保数据源是流式(IEnumerable)而非全内存集合

高级场景

追加写入现有文件:

using (var writer = new StreamWriter(filePath, append: true)) // 关键参数
{
    writer.WriteLine("----- 这是追加的内容 -----");
}

混合同步/异步写入

var writer = new StreamWriter(filePath);
await writer.WriteLineAsync("Header");  // 异步写开头
writer.WriteLine("Sync Content");       // 同步写主体
await writer.FlushAsync();              // 手动异步刷新

到此这篇关于C#实现高性能写入txt大量数据的文章就介绍到这了,更多相关C# txt数据写入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#连接mysql的方法【基于vs2010】

    C#连接mysql的方法【基于vs2010】

    这篇文章主要介绍了C#连接mysql的方法,基于vs2010平台较为详细的讲述了C#操作mysql所需的组件下载、安装及连接mysql操作实现代码,需要的朋友可以参考下
    2017-03-03
  • C#简单读写txt文件的方法

    C#简单读写txt文件的方法

    这篇文章主要介绍了C#简单读写txt文件的方法,涉及C#针对文件的基本打开、写入、保存与读取等操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2016-06-06
  • C#实现标签打印工具的设计方案

    C#实现标签打印工具的设计方案

    本文详细介绍了C#实现标签打印工具的设计方案,包括系统架构设计、核心功能模块、数据流实现、关键技术创新、测试用例、部署方案以及扩展功能建议,需要的朋友可以参考下
    2026-03-03
  • 详解C#如何实现分割视频

    详解C#如何实现分割视频

    这篇文章主要为大家详细介绍了C#如何实现将视频文件分割成一帧帧图片的方法,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • c#将list类型转换成DataTable方法示例

    c#将list类型转换成DataTable方法示例

    将List类型转换成DataTable的通用方法,大家参考使用吧
    2013-12-12
  • C#在MEF框架中手动导入依赖模块

    C#在MEF框架中手动导入依赖模块

    这篇文章介绍了C#在MEF框架中手动导入依赖模块的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • C#代码实现读取并导出PDF书签

    C#代码实现读取并导出PDF书签

    PDF 书签(大纲)是文档导航的核心要素,本文将介绍如何使用 Free Spire.PDF for .NET 库,通过 C# 代码完整读取 PDF 文件中的所有书签,感兴趣的小伙伴可以了解下
    2026-04-04
  • C#实现获取文件大小并进行比较

    C#实现获取文件大小并进行比较

    这篇文章主要为大家详细介绍了C#如何实现获取文件大小进行单位转换与文件大小比较功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-03-03
  • C# XML基础入门小结(XML文件内容增删改查清)

    C# XML基础入门小结(XML文件内容增删改查清)

    本文主要介绍了C# XML基础入门小结(XML文件内容增删改查清),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • C#中感叹号(!) 的作用总结

    C#中感叹号(!) 的作用总结

    这篇文章主要给大家总结介绍了C#中感叹号(!) 的作用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12

最新评论