简体   繁体   English

提取不存在的文件

[英]Fetching files that don't exist

I have a function which I use to recursively rename files within a particular folder, like this: 我有一个函数,用于递归重命名特定文件夹中的文件,如下所示:

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... */
    }
}

However, file.IsReadOnly = false , will, on random occasion, throw a FileNotFoundException exception. 但是, file.IsReadOnly = false会在随机情况下引发FileNotFoundException异常。 After looking at the stack trace and information provided by the exception, I can use the provided full path and locate the "missing" file every time this exception occurs. 在查看了异常提供的堆栈跟踪和信息之后,我可以使用提供的完整路径并在每次发生此异常时定位“丢失”文件。

Again, this seems to occur on random occasions, usually whenever the application encounters a file that is in read-only mode, and it tries to make it writable. 同样,这似乎是随机发生的,通常是在应用程序遇到只读模式的文件时,它会尝试使其可写。 The program does not always break on the same file each time. 该程序并不总是每次都在同一个文件上中断。

I am the administrator on the machine, and have full permissions to this folder and all of its sub-folders and files. 我是计算机的管理员,并且对此文件夹及其所有子文件夹和文件拥有完全权限。 None of these files or directories are hidden. 这些文件或目录均未隐藏。

So, I'm curious as to why dirInfo.GetFiles() is returning files that C# thinks don't exist. 因此,我很好奇为什么dirInfo.GetFiles()返回C#认为不存在的文件。 Does anyone have any insight as to why this is happening? 是否有人对此有何见解?

Firstly, you don't have to implement recursion for this as the Directory.EnumerateFiles() takes a SearchOption parameter allowing you to include subdirectories. 首先,您不必为此执行递归,因为Directory.EnumerateFiles()带有SearchOption参数,允许您包含子目录。 Not that this will solve your problem, but simpler code is always good, so thought I'd include the tip. 并不是说这可以解决您的问题,但是简单的代码总是好的,因此,我想将其包括在内。

I think Adarsha (comment on your question) is onto something. 我认为Adarsha(对您的问题的评论)有些问题。 But how can you use that to your advantage? 但是,如何利用它来发挥自己的优势呢? I have two approaches in mind. 我有两种思路。 There might be more.. 可能还有更多..

  1. Implement your logic so that it recovers gracefully when something bad like this occurrs. 实施您的逻辑,以便在出现此类不良情况时能够正常恢复。 Most likely through one or more layers of retries and/or reruns. 最有可能通过一层或多层重试和/或重新运行。 For example your inner code could retry once if the exception is caught. 例如,如果捕获到异常,您的内部代码可以重试一次。 If it happens again, rethrow and let the consuming code handle it. 如果再次发生,请重新抛出并让使用方的代码处理它。 Then let your consuming code rerun the whole loop after some sleep or whatever to let your file system settle down. 然后,让您的消耗代码在睡眠后或重新启动文件系统后,重新运行整个循环。

  2. Use NTFS Transactions. 使用NTFS事务。 Only available if your code will run on Vista/2008 or later. 仅当您的代码将在Vista / 2008或更高版本上运行时才可用。 That stuff is in the windowsapi, so if you're uncomfortable with marshalling, you could use a prewritten wrapper such as Transactional NTFS over at codeplex. 这些东西在windowsapi中,因此,如果您对编组感到不舒服,可以在codeplex上使用诸如Transactional NTFS之类的预包装器。 Not sure if you can lock your directories using that, but I think you can through Txf.Directory.GetDirectory(..) while providing your ambient transaction scope. 不知道是否可以使用它来锁定目录,但是我认为您可以通过Txf.Directory.GetDirectory(..)来提供环境事务范围。

Best of luck! 祝你好运! :) :)

I'm not really sure why DirectoryInfo will give you files that the system does not think exists; 我不太确定DirectoryInfo为什么会向您提供系统认为不存在的文件。 however, in order to help you with your exception. 但是,为了帮助您解决例外情况。 You should look into this : 您应该调查一下:

http://msdn.microsoft.com/en-us/library/system.io.fileinfo.exists(v=vs.110).aspx 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);

    }
}

Edit based on comments: 根据评论进行编辑:

You should take a look at this overload if you suspect that another part of the program has the file locked. 如果您怀疑程序的另一部分已锁定文件,则应查看此重载。

http://msdn.microsoft.com/en-us/library/5h0z48dh(v=vs.110).aspx http://msdn.microsoft.com/en-us/library/5h0z48dh(v=vs.110).aspx

Here is an example from a past piece of code showing how you can use it (since I feel msdn lacks a meaningful example) 这是过去一段代码中的示例,展示了如何使用它(因为我觉得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);
        }
    }

The code above gets a file that was created in memory via decompression (header.GetStream()) and then creates a physical file on the desk in the application Data and opens that file. 上面的代码获取通过解压缩(header.GetStream())在内存中创建的文件,然后在应用程序Data的桌面上创建物理文件并打开该文件。

By specifying multiple FileShares I can allow for the file to be accessed in multiple ways. 通过指定多个FileShare,我可以允许以多种方式访问​​文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM