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

使用File.Move时重复执行引发文件不存在错误的问题

问题:File.Move重复执行导致文件不存在报错

现象

执行文件移动操作时,系统提示源目录中文件不存在,但实际文件已经被移动。排查后发现File.Move被执行了两次;移除File.OpenRead相关代码后,移动功能恢复正常,但业务需要先读取文件内容再执行移动。

读取文件的原始代码

StreamReader reader = null;
reader = new StreamReader(File.OpenRead(path+"/"+fileName));

文件移动代码

if (File.Exists(path + "/" + fileName))
{
    lock (fileMoveLock)
    {
        string timeStamp = GetTimestamp(DateTime.Now);
        Console.WriteLine(timeStamp);

        string fileNameSlice = fileName.Substring(0, (fileName.Length - 4));
        string finalPath = fileNameSlice + "_" + timeStamp + ".txt";

        try
        {
            File.Move(path + "/" + fileName, Path.Combine(path + "/archive", finalPath));
            Console.WriteLine($"File moved: {path + "/" + fileName} to {finalPath}");
        }
        catch (Exception ex)
        {
            // Handle any exceptions that may occur during the move operation
            Console.WriteLine($"Error moving file: {ex.Message}");
        }
    }
}
else
{
    // Handle the case where the file does not exist
    return;
}

已尝试的无效操作

  • 使用后手动关闭/释放流,依然出现File.Move执行两次的情况
  • 添加Thread.Sleep无效果
  • 加锁fileMoveLock也无法解决问题
  • 试过以下写法,但不确定是否属于不良实践:
try
{
    StreamReader reader = null;
    reader = new StreamReader(File.OpenRead(path + "/" + fileName));
}
catch (Exception ex) 
{
    return;
}

问题分析与解决方案

核心原因

File.OpenRead打开文件后,如果没有正确释放资源,会导致文件句柄未被完全释放,可能触发重复执行的逻辑(比如文件监控事件、重复调用的业务流程),进而导致File.Move被调用两次。第一次移动成功后,第二次调用时源文件已不存在,就会报错。

正确的文件读取方式

必须确保文件流被正确释放,推荐使用using语句(自动释放资源),这是.NET中处理可释放资源的标准做法,完全不属于不良实践:

try
{
    using (StreamReader reader = new StreamReader(File.OpenRead(Path.Combine(path, fileName))))
    {
        // 在这里读取文件内容,例如:
        string content = reader.ReadToEnd();
        // 处理读取到的数据
    }
}
catch (Exception ex)
{
    Console.WriteLine($"读取文件出错:{ex.Message}");
    return;
}
  • using语句会在代码块结束时自动调用Dispose(),彻底释放文件句柄,确保文件不再被占用
  • 用Path.Combine替代手动拼接路径,避免路径分隔符的兼容问题

额外优化点

  1. 移除File.Exists检查,改用捕获异常处理文件不存在的情况(避免检查后到移动前的竞态条件):
lock (fileMoveLock)
{
    string timeStamp = GetTimestamp(DateTime.Now);
    Console.WriteLine(timeStamp);

    string fileNameSlice = fileName.Substring(0, fileName.Length - 4);
    string finalPath = fileNameSlice + "_" + timeStamp + ".txt";
    string sourcePath = Path.Combine(path, fileName);
    string destPath = Path.Combine(path, "archive", finalPath);

    try
    {
        File.Move(sourcePath, destPath);
        Console.WriteLine($"文件已移动:{sourcePath} -> {finalPath}");
    }
    catch (FileNotFoundException)
    {
        Console.WriteLine("源文件不存在,无需移动");
        return;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"移动文件出错:{ex.Message}");
    }
}
  1. 确保fileMoveLock是类级别的静态对象,否则锁无法跨线程生效:
private static readonly object fileMoveLock = new object();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:43:32