C#读取源文件追加到新文件后无法移动原文件的IOException报错如何解决
问题原因
你碰到的IOException确实大概率是源文件锁未释放导致的,核心原因有两个:
File.ReadLines返回的是延迟枚举的迭代器,虽然正常遍历结束后会自动释放资源,但极端场景下(比如迭代过程中出现未捕获的异常、运行时GC未及时触发清理)会导致文件句柄没有即时释放- 部分.NET版本下
File.ReadLines的内部句柄释放存在微小的延迟,遍历结束后立刻调用File.Move很容易撞上未释放的锁
解决方法
方案1:显式控制文件读取的资源生命周期
不用File.ReadLines,改用StreamReader配合using块包裹读取逻辑,保证读取结束后立刻强制释放源文件句柄,兼容性最好,也支持大文件读取:
var stringwrite = new[] { prefix, prefix2 }; // using块退出时会自动销毁StreamReader,立刻释放源文件的锁 using (var reader = new StreamReader(currentFile)) { string line; while ((line = reader.ReadLine()) != null) { var lastOne = line.Split(';').Last(); if (!stringwrite.Any(s => lastOne.Contains(s))) continue; File.AppendAllText(todestination, line + Environment.NewLine); } } // 到这里源文件句柄已经确定释放,可以安全移动 try { File.Move(currentFile, completeddestination); break; } catch (Exception ex) { MessageBox.Show("移动文件出错: " + ex.Message); }
方案2:小文件场景直接全量加载到内存
如果处理的源文件体积不大(几十MB以内),可以直接用File.ReadAllLines一次性把所有内容加载到内存,读取操作完成后就会立刻释放源文件锁,代码改动最小:
var stringwrite = new[] { prefix, prefix2 }; // ReadAllLines不会持有文件锁,读取完成立刻释放源文件 foreach (string line in File.ReadAllLines(currentFile)) { var lastOne = line.Split(';').Last(); if (!stringwrite.Any(stringwrite => lastOne.Contains(stringwrite))) continue; File.AppendAllText(todestination, line + Environment.NewLine); } // 后续移动文件逻辑不变
额外优化建议
你原有代码中循环内每次调用File.AppendAllText,每次都会打开、关闭一次目标文件,IO开销非常高,也可以同步改成StreamWriter批量写入,大幅提升处理效率:
var stringwrite = new[] { prefix, prefix2 }; // 同时控制源文件读取、目标文件写入的资源生命周期 using (var reader = new StreamReader(currentFile)) using (var writer = new StreamWriter(todestination, append: true)) // append:true对应原有追加写入的逻辑 { string line; while ((line = reader.ReadLine()) != null) { var lastOne = line.Split(';').Last(); if (!stringwrite.Any(s => lastOne.Contains(s))) continue; writer.WriteLine(line); } } // 后续移动文件逻辑不变
内容的提问来源于stack exchange,提问作者cragjungle
相关产品推荐
相关产品推荐

