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

C#使用StreamWriter合并CSV二次执行时报文件被进程占用错误

问题描述

我使用C#尝试将多个CSV文件合并为单个CSV文件。
该功能首次运行可以正常生效,但第二次执行时会出现如下报错:

"The process cannot access the file "c:\test\CSV_merged.csv because it is being used by another process"

通过ProcessExplorer排查得知,该文件正被我开发的应用程序(CSV_Merge.exe)占用。
但奇怪的是,我可以通过Windows资源管理器删除"c:\test\CSV_merged.csv"文件(即便它处于锁定状态?),删除后第二次执行合并功能即可正常运行。
我已经尝试使用using (StreamWriter....)语句块,还额外调用了Flush()、Close()、Dispose()方法——按理说使用using (StreamWriter....)语句时本不需要手动调用这些释放方法?
以下是我的实现代码:

private void btnMergeCSVFiles_Click(object sender, EventArgs e)
{
    string sourceFolder = lblSelectedCSVFolder.Text;
    string destinationFile = lblSelectedCSVFolder.Text + "\\CSV_Files_Combined.csv";

    // Specify wildcard search to match CSV files that will be combined
    string[] CSVFiles = Directory.GetFiles(sourceFolder, "*.csv");

    using (StreamWriter fileDest = new StreamWriter(destinationFile))
    {
        //StreamWriter fileDest = new StreamWriter   (destinationFile, true);

        int i;
        for (i = 0; i < CSVFiles.Length; i++)
        {
            string file = CSVFiles[i];

            string[] lines = File.ReadAllLines(file);

            if (chkBoxCSVHasHeaderline.Checked && i > 0)
            {
                lines = lines.Skip(1).ToArray(); // Skip header row for all but first file
            }

            foreach (string line in lines)
            {
                fileDest.WriteLine(line);
            }
        }

        //fileDest.Flush();
        //fileDest.Close();
        //fileDest.Dispose();
    }

    //fileDest.Flush();
    //fileDest.Close();
    //fileDest.Dispose();
}

运行报错截图

问题原因

你的代码出现文件占用报错和资源释放没有关系,using (StreamWriter...) 块会在执行结束(包括抛出异常时)自动正确释放文件句柄,你手动加的Flush()/Close()/Dispose()都是多余的,完全不需要额外调用。
触发报错的根本原因是输出文件存放路径和待合并CSV在同一个文件夹,且你枚举了该文件夹下所有.csv文件作为合并源:

  • 第一次运行时,合并后的输出文件还不存在,Directory.GetFiles 枚举到的只有你需要合并的源CSV文件,流程正常执行,跑完后输出文件被生成在源文件夹下。
  • 第二次运行时,Directory.GetFiles 会把上次生成的合并输出文件也当成待合并的源文件加入处理列表。你首先通过StreamWriter以写权限打开了输出文件并持有句柄,当循环处理到输出文件本身时,File.ReadAllLines 尝试以读权限打开该文件,由于Windows文件共享权限的双向校验规则,这一操作会和已存在的写句柄冲突,直接抛出文件被占用的错误。

你能在资源管理器里删除被锁定的文件,是因为Windows系统支持对打开的文件标记删除状态,等所有持有该文件的句柄关闭后就会真正执行删除;删除后第二次运行时,GetFiles 枚举不到输出文件,就和第一次运行的场景一致,自然可以正常执行。
你在Process Explorer中看到文件被自己的程序占用,是因为报错发生时程序还处于using块的执行流程中,StreamWriter持有的文件句柄还没到释放时机,属于正常现象,不是资源泄漏。

修复方案

两种方案选其一即可:

  • 将合并后的输出文件存放到源CSV文件夹之外的其他目录,从根源上避免输出文件被枚举为待合并源。
  • 如果必须把输出文件放在源文件夹下,在获取CSV文件列表后,显式将输出文件从待处理列表中过滤掉,参考代码:
    string[] CSVFiles = Directory.GetFiles(sourceFolder, "*.csv")
        .Where(filePath => !filePath.Equals(destinationFile, StringComparison.OrdinalIgnoreCase))
        .ToArray();
    
可选优化
  • 路径拼接建议使用Path.Combine()方法,不要手动拼接\\,避免路径末尾自带斜杠、跨系统兼容等问题,比如string destinationFile = Path.Combine(lblSelectedCSVFolder.Text, "CSV_Files_Combined.csv");
  • 如果需要合并体积较大的CSV文件,不建议用File.ReadAllLines把整个文件一次性读入内存,可以改用流逐行读写,大幅降低内存占用,优化后的参考代码如下:
    private void btnMergeCSVFiles_Click(object sender, EventArgs e)
    {
        string sourceFolder = lblSelectedCSVFolder.Text;
        string destinationFile = Path.Combine(sourceFolder, "CSV_Files_Combined.csv");
    
        // 枚举所有csv文件,排除输出文件自身
        string[] CSVFiles = Directory.GetFiles(sourceFolder, "*.csv")
            .Where(f => !f.Equals(destinationFile, StringComparison.OrdinalIgnoreCase))
            .ToArray();
    
        using (StreamWriter fileDest = new StreamWriter(destinationFile))
        {
            for (int i = 0; i < CSVFiles.Length; i++)
            {
                bool skipHeader = chkBoxCSVHasHeaderline.Checked && i > 0;
                
                using (StreamReader reader = new StreamReader(CSVFiles[i]))
                {
                    string line;
                    if (skipHeader)
                    {
                        // 跳过非首个文件的表头行
                        reader.ReadLine();
                    }
                    while ((line = reader.ReadLine()) != null)
                    {
                        fileDest.WriteLine(line);
                    }
                }
            }
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:27:26