我们通过将新记录写入临时文件,然后用临时文件替换旧文件来执行大型文本文件的更新.一个严重缩写的版本:
var tpath = Path.GetTempFileName(); try { using (var sf = new StreamReader(sourcepath)) using (var tf = new StreamWriter(tpath)) { string line; while ((line = sf.ReadLine()) != null) tf.WriteLine(UpdateLine(line)); } File.Delete(sourcepath); File.Move(tpath, sourcepath); } catch { File.Delete(tpath); throw; }
如果有任何异常抛出异常(找不到文件,没有权限),原始文件保持不变,这就是我们想要的.
但是,代码存在以下问题:
是否存在真实的情况,Delete
但是Move
失败了?这将删除原始数据和更新数据.这会很糟糕.
最常见的故障是源文件从另一个应用程序打开,并且Delete
失败.这意味着将丢弃所有更新工作.有没有办法查看源文件在开始时是否可删除,如果没有则放弃更新?
我们让用户将Windows资源管理器摘要属性(如标题或注释)放在文件上.删除文件时会丢弃这些内容.有没有办法将旧文件的Summary属性复制到新文件?我们应该这样做吗?
Jon Skeet.. 5
避免"删除然后移动失败问题"的正常方法是:
写入file.new
将file.current移动到file.old
将file.new移动到file.current
删除file.new
然后当你来阅读时,如果缺少file.current,则使用file.new,如果你看到则删除file.old.
检查文件是否可用:尝试将其打开以进行写入,但附加到结尾.当然,你需要在移动它之前关闭手柄,而在其他人之间可以打开它 - 但这至少是一个合理的优化.
我不敢确定复制摘要等.
避免"删除然后移动失败问题"的正常方法是:
写入file.new
将file.current移动到file.old
将file.new移动到file.current
删除file.new
然后当你来阅读时,如果缺少file.current,则使用file.new,如果你看到则删除file.old.
检查文件是否可用:尝试将其打开以进行写入,但附加到结尾.当然,你需要在移动它之前关闭手柄,而在其他人之间可以打开它 - 但这至少是一个合理的优化.
我不敢确定复制摘要等.