获取不存在的文件
本文关键字:文件 不存在 获取 | 更新日期: 2023-09-27 18:12:01
我有一个函数,我用它来递归地重命名特定文件夹中的文件,像这样:
public void renameRecur(string destination)
{
DirectoryInfo dirInfo = new DirectoryInfo(destination);
//Rename each of the files
foreach(FileInfo file in dirInfo.GetFiles())
{
file.IsReadOnly = false;
/* Rename files and things... */
}
//Rename each of the directories
foreach(DirectoryInfo dir in dirInfo.EnumerateDirectories())
{
renameRecur(dir.FullName);
/* Rename directories and things... */
}
}
但是,file.IsReadOnly = false
将在随机情况下抛出FileNotFoundException
异常。在查看了异常提供的堆栈跟踪和信息之后,我可以使用提供的完整路径,并在每次发生此异常时定位"丢失"的文件。
同样,这似乎在随机情况下发生,通常是当应用程序遇到一个处于只读模式的文件,并试图使其可写时。程序并不总是每次都在同一个文件上中断。
我是机器的管理员,对这个文件夹及其所有子文件夹和文件有完全的权限。这些文件或目录都不隐藏。
所以,我很好奇为什么dirInfo.GetFiles()
返回C#
认为不存在的文件。有人知道为什么会这样吗?
首先,您不必为此实现递归,因为Directory.EnumerateFiles()
接受一个SearchOption参数,允许您包含子目录。这并不能解决您的问题,但是更简单的代码总是好的,所以我认为我应该包括这个技巧。
我认为Adarsha(评论你的问题)说到点子上了。但你如何利用这一点呢?我有两个想法。
-
实现您的逻辑,以便在发生类似这样的错误时优雅地恢复。最可能的是通过一个或多个重试和/或重新运行层。例如,如果捕获异常,内部代码可以重试一次。如果再次发生,重新抛出并让消费代码处理它。然后让你的消费代码在一些睡眠或其他什么之后重新运行整个循环,让你的文件系统安定下来。
-
使用NTFS事务。仅当您的代码将在Vista/2008或更高版本上运行时可用。这些东西都在windowsapi中,所以如果你不喜欢编组,你可以使用一个预先编写的包装器,比如codeplex上的Transactional NTFS。不确定你是否可以使用它来锁定你的目录,但我认为你可以通过
Txf.Directory.GetDirectory(..)
来提供你的环境事务范围。
我不太确定为什么DirectoryInfo会给你系统认为不存在的文件;但是,为了帮助您处理您的例外情况。你应该看看这个:
http://msdn.microsoft.com/en-us/library/system.io.fileinfo.exists (v = vs.110) . aspx
public void renameRecur(string destination) {
DirectoryInfo dirInfo = new DirectoryInfo(destination);
foreach(FileInfo file in dirInfo.getFiles()) {
if(!file.Exists) //Try This.
continue;
file.IsReadOnly = false;
}
foreach(DirectoryInfo dir in dirInfo.EnumerateDirectories()) {
renameRecur(dir.FullName);
}
}
根据注释编辑:
如果您怀疑程序的另一部分锁定了该文件,则应该查看此重载。
http://msdn.microsoft.com/en-us/library/5h0z48dh (v = vs.110) . aspx
下面是过去一段代码中的一个示例,展示了如何使用它(因为我觉得msdn缺乏一个有意义的示例)
void ExternOpen(FileHeader header)
{
var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var appDataLocation = appData + @"'" + header;
using (var fs = new FileStream(appDataLocation, FileMode.Create, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete))
using (var hs = header.GetStream())
{
hs.CopyTo(fs);
Process.Start(appDataLocation);
}
}
上面的代码通过解压缩(header.GetStream())在内存中创建一个文件,然后在应用程序Data的桌面上创建一个物理文件,并打开该文件。
通过指定多个文件共享,我可以允许以多种方式访问文件。