我有一个Web服务正在编写由其他程序读取的文件。
为了使阅读器程序在编写完成之前无法读取它们,我正在使用.tmp扩展名对其进行编写,然后使用File.Move将其重命名为.xml扩展名。
我的问题是,当我们批量运行时-短短几分钟内成千上万个文件。
我已经成功写入文件“ 12345.tmp”,但是当我尝试重命名它时,File.Move()
会抛出IOException
:
File.Move("12345.tmp", "12345.xml")
异常:进程无法访问文件,因为正在使用该文件 通过另一个过程。
对于我的情况,我并不在乎文件名是什么,所以我重试:
File.Move("12345.tmp", "12346.xml")
异常:异常:找不到文件'12345.tmp'。
如果File.Move()
在重命名文件时遇到错误,是否要删除源文件?
为什么?
是否有办法确保文件重命名成功或保持不变?
答案 0 :(得分:2)
答案是,这很大程度上取决于文件系统本身的实现方式。同样,如果Move()在两个文件系统之间(甚至在两台机器之间,如果路径是网络共享),那么它也很大程度上取决于Move()的O / S实现。因此,保证将更少依赖于System.IO.File的工作,而更多地依赖于底层机制:O / S代码,文件系统驱动程序,文件系统结构等。
通常,在大多数情况下,Move()会按照您期望的方式运行:移动文件或保持原样。这是因为在单个文件系统中移动是从一个目录(磁盘数据结构)中删除文件 reference 并将其添加到另一个目录中的动作。如果发生问题,则将回滚该操作:通过相反的插入操作撤消从源目录中删除的操作。大多数现代文件系统都具有内置的日志记录机制,即使在操作过程中计算机断电的情况下,也可以确保完全执行移动操作或完全回滚移动操作。
话虽如此,但这仍然取决于,并非所有文件系统都提供这些保证。 See this study
如果您在Windows上运行,并且文件系统是本地的(不是网络共享),则可以使用Windows的Transacitonal File System (TxF) feature来确保移动操作的原子性。