Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net Directory.EnumerateFiles=>;未经授权的访问例外_.net_Filesystems_Lazy Evaluation_Unauthorizedaccessexcepti - Fatal编程技术网

.net Directory.EnumerateFiles=>;未经授权的访问例外

.net Directory.EnumerateFiles=>;未经授权的访问例外,.net,filesystems,lazy-evaluation,unauthorizedaccessexcepti,.net,Filesystems,Lazy Evaluation,Unauthorizedaccessexcepti,在.NET4.0中有一个很好的新方法,可以通过枚举以流方式获取目录中的文件 这里的问题是,如果希望枚举所有文件,可能事先不知道哪些文件或文件夹受访问保护,并且可能引发UnauthorizedAccessException 要复制,只需运行以下片段: foreach (var file in Directory.EnumerateFiles(@"c:\", "*", SearchOption.AllDirectories)) { // whatever } 在这个.NET方法出现之前,通过

在.NET4.0中有一个很好的新方法,可以通过枚举以流方式获取目录中的文件

这里的问题是,如果希望枚举所有文件,可能事先不知道哪些文件或文件夹受访问保护,并且可能引发UnauthorizedAccessException

要复制,只需运行以下片段:

foreach (var file in Directory.EnumerateFiles(@"c:\", "*", SearchOption.AllDirectories))
{
   // whatever
}
在这个.NET方法出现之前,通过在字符串数组返回方法上实现递归迭代器,可以实现大致相同的效果。但它并不像新的.NET方法那么懒惰

那怎么办呢?使用此方法时,是否可以抑制UnauthorizedAccessException,或者它是一个事实


在我看来,该方法应该有一个重载,接受处理任何异常的操作。

我知道引发异常的是
MoveNext

我尝试编写一个方法,该方法可以安全地遍历序列,并尝试忽略
MoveNext
异常。然而,我不确定当它抛出异常时,
MoveNext
是否会推进位置,所以这也可能是无限循环。这也是一个坏主意,因为我们将依赖于实施细节

但这真是太有趣了

public static IEnumerable<T> SafeWalk<T> (this IEnumerable<T> source)
{
    var enumerator = source.GetEnumerator();
    bool? hasCurrent = null;

    do {
        try {
            hasCurrent = enumerator.MoveNext();
        } catch {
            hasCurrent = null; // we're not sure
        }

        if (hasCurrent ?? false) // if not sure, do not return value
            yield return enumerator.Current;

    } while (hasCurrent ?? true); // if not sure, continue walking
}

foreach (var file in Directory.EnumerateFiles("c:\\", "*", SearchOption.AllDirectories)
                              .SafeWalk())
{
    // ...
}
公共静态IEnumerable安全行走(此IEnumerable源代码)
{
var枚举器=source.GetEnumerator();
bool?hasCurrent=null;
做{
试一试{
hasCurrent=enumerator.MoveNext();
}抓住{
hasCurrent=null;//我们不确定
}
if(hasCurrent??false)//如果不确定,则不返回值
产生返回枚举数。当前;
}while(hasCurrent??true);//如果不确定,继续行走
}
foreach(目录.EnumerateFiles(“c:\\”、“*”、SearchOption.AllDirectory)中的var文件)
.SafeWalk())
{
// ...
}
只有当框架实现此迭代器的以下条件为真时,这才有效(请参阅Reflector中的
FileSystemMemerableTerator
):

  • MoveNext
    在失败时前进其位置
  • 当最后一个元素
    MoveNext
    失败时,后续调用将返回
    false
    ,而不是抛出异常
  • 对于不同版本的.NET Framework,此行为是一致的
  • 我没有犯任何逻辑或语法错误
即使它有效,请不要在生产中使用它

但是我真的很想知道它是否真的起作用。

我无法让上面的内容起作用,但这是我的实现,我已经在“Win7”框中的c:\users上对它进行了测试,因为if有所有这些“讨厌的”目录:

类别:

public static class SafeWalk
{
    public static IEnumerable<string> EnumerateFiles(string path, string searchPattern, SearchOption searchOpt)
    {   
        try
        {
            var dirFiles = Enumerable.Empty<string>();
            if(searchOpt == SearchOption.AllDirectories)
            {
                dirFiles = Directory.EnumerateDirectories(path)
                                    .SelectMany(x => EnumerateFiles(x, searchPattern, searchOpt));
            }
            return dirFiles.Concat(Directory.EnumerateFiles(path, searchPattern));
        }
        catch(UnauthorizedAccessException ex)
        {
            return Enumerable.Empty<string>();
        }
    }
}
公共静态类安全行走
{
公共静态IEnumerable枚举文件(字符串路径、字符串搜索模式、SearchOption searchOpt)
{   
尝试
{
var dirFiles=Enumerable.Empty();
if(searchOpt==SearchOption.AllDirectories)
{
dirFiles=目录。枚举目录(路径)
.SelectMany(x=>枚举文件(x,searchPattern,searchOpt));
}
返回dirFiles.Concat(Directory.EnumerateFiles(path,searchPattern));
}
捕获(未经授权的访问例外)
{
返回可枚举的.Empty();
}
}
}

上述答案的问题是,不考虑子目录中的异常。这是处理这些异常的更好方法,因此您可以从所有子目录中获取所有文件,但存在访问异常的文件除外:

    /// <summary>
    /// A safe way to get all the files in a directory and sub directory without crashing on UnauthorizedException or PathTooLongException
    /// </summary>
    /// <param name="rootPath">Starting directory</param>
    /// <param name="patternMatch">Filename pattern match</param>
    /// <param name="searchOption">Search subdirectories or only top level directory for files</param>
    /// <returns>List of files</returns>
    public static IEnumerable<string> GetDirectoryFiles(string rootPath, string patternMatch, SearchOption searchOption)
    {
        var foundFiles = Enumerable.Empty<string>();

        if (searchOption == SearchOption.AllDirectories)
        {
            try
            {
                IEnumerable<string> subDirs = Directory.EnumerateDirectories(rootPath);
                foreach (string dir in subDirs)
                {
                    foundFiles = foundFiles.Concat(GetDirectoryFiles(dir, patternMatch, searchOption)); // Add files in subdirectories recursively to the list
                }
            }
            catch (UnauthorizedAccessException) { }
            catch (PathTooLongException) {}
        }

        try
        {
            foundFiles = foundFiles.Concat(Directory.EnumerateFiles(rootPath, patternMatch)); // Add files from the current directory
        }
        catch (UnauthorizedAccessException) { }

        return foundFiles;
    }
//
///获取目录和子目录中所有文件的安全方法,而不会因未经授权的异常或PathTooLongException而崩溃
/// 
///起始目录
///文件名模式匹配
///搜索子目录或仅搜索顶级目录中的文件
///文件清单
公共静态IEnumerable GetDirectoryFiles(字符串根路径、字符串模式匹配、搜索选项搜索选项)
{
var foundFiles=Enumerable.Empty();
if(searchOption==searchOption.AllDirectories)
{
尝试
{
IEnumerable subDirs=目录。枚举目录(根路径);
foreach(子目录中的字符串目录)
{
foundFiles=foundFiles.Concat(GetDirectoryFiles(dir,patternMatch,searchOption));//将子目录中的文件递归添加到列表中
}
}
捕获(UnauthorizedAccessException){}
catch(PathTooLongException){}
}
尝试
{
foundFiles=foundFiles.Concat(Directory.EnumerateFiles(rootPath,patternMatch));//从当前目录添加文件
}
捕获(UnauthorizedAccessException){}
归还文件;
}

我迟到了,但我建议改用可观察模式:

public class FileUtil
{
  private static void FindFiles_(string path, string pattern,
    SearchOption option, IObserver<string> obs, CancellationToken token)
  {
    try
    {
      foreach (var file in Directory.EnumerateFiles(path, pattern,
        SearchOption.TopDirectoryOnly))
      {
        if (token.IsCancellationRequested) break;
        obs.OnNext(file);
      }

      if (option != SearchOption.AllDirectories) return;

      foreach (var dir in Directory.EnumerateDirectories(path, "*", 
        SearchOption.TopDirectoryOnly))
      {
        FindFiles_(dir, pattern, option, obs, token);
      }
    }
    catch (UnauthorizedAccessException) { }
    catch (PathTooLongException) { }
    catch (IOException) { }
    catch (Exception err) { obs.OnError(err); }
  }

  public static IObservable<string> GetFiles(string root, string pattern,
    SearchOption option)
  {
    return Observable.Create<string>(
      (obs, token) =>
        Task.Factory.StartNew(
          () =>
          {
            FindFiles_(root, pattern, option, obs, token);
            obs.OnCompleted();
          },
          token));
  }
}
公共类FileUtil
{
私有静态void FindFiles(字符串路径、字符串模式、,
SearchOption选项、IObserver obs、CancellationToken(令牌)
{
尝试
{
foreach(目录中的var文件。枚举文件(路径、模式、,
SearchOption.TopDirectoryOnly)
{
如果(token.IsCancellationRequested)中断;
obs.OnNext(文件);
}
if(option!=SearchOption.AllDirectories)返回;
foreach(目录中的var dir.EnumerateDirectories(路径“*”,
SearchOption.TopDirectoryOnly)
{
FindFiles(目录、模式、选项、obs、令牌);
}
}
捕获(UnauthorizedAccessException){}
catch(PathTooLongException){}
捕获(IOException){}
捕获(异常错误){obs.OnError(错误);}
}
公共静态IObservable GetFiles(字符串根、字符串模式、,
搜索选项(可选)
{
返回可观察的。创建(
(obs,令牌)=>
Task.Factory.StartNew(
() =>
{
FindF
public class FileUtil
{
  private static void FindFiles_(string path, string pattern,
    SearchOption option, IObserver<string> obs, CancellationToken token)
  {
    try
    {
      foreach (var file in Directory.EnumerateFiles(path, pattern,
        SearchOption.TopDirectoryOnly))
      {
        if (token.IsCancellationRequested) break;
        obs.OnNext(file);
      }

      if (option != SearchOption.AllDirectories) return;

      foreach (var dir in Directory.EnumerateDirectories(path, "*", 
        SearchOption.TopDirectoryOnly))
      {
        FindFiles_(dir, pattern, option, obs, token);
      }
    }
    catch (UnauthorizedAccessException) { }
    catch (PathTooLongException) { }
    catch (IOException) { }
    catch (Exception err) { obs.OnError(err); }
  }

  public static IObservable<string> GetFiles(string root, string pattern,
    SearchOption option)
  {
    return Observable.Create<string>(
      (obs, token) =>
        Task.Factory.StartNew(
          () =>
          {
            FindFiles_(root, pattern, option, obs, token);
            obs.OnCompleted();
          },
          token));
  }
}
public static class SafeWalk
{
    public static IEnumerable<string> EnumerateFiles(string path, string searchPattern, SearchOption searchOpt)
    {
        if (searchOpt == SearchOption.TopDirectoryOnly)
        {
            return Directory.EnumerateFiles(path, searchPattern, SearchOption.TopDirectoryOnly);
        }

        List<string> folders = new List<string>() { path };
        int folCount = 1;
        List<string> files = new List<string>() { };

        for (int i = 0; i < folCount; i++)
        {
            try
            {
                foreach (var newDir in Directory.EnumerateDirectories(folders[i], "*", SearchOption.TopDirectoryOnly))
                {
                    folders.Add(newDir);
                    folCount++;
                    try
                    {

                        foreach (var file in Directory.EnumerateFiles(newDir, searchPattern))
                        {
                            files.Add(file);
                        }
                    } catch (UnauthorizedAccessException)
                    {
                        // Failed to read a File, skipping it.
                    }
                }
            }
            catch (UnauthorizedAccessException)
            {
                // Failed to read a Folder, skipping it.
                continue;
            }
        }
        return files;
    }
}
static IEnumerable<string> FindFiles(string path, string filter = "*", bool recursive = false)
{
    IEnumerator<string> fEnum;
    try
    {
        fEnum = Directory.EnumerateFiles(path, filter, recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).GetEnumerator();
    }
    catch (UnauthorizedAccessException) { yield break; }
    while (true)
    {
        try { if (!fEnum.MoveNext()) break; }
        catch (UnauthorizedAccessException) { continue; }
        yield return fEnum.Current;
    }
}