获取所有文件和目录列表的初学者友好方法

时间:2009-10-10 03:39:16

标签: c# directory

使用.NET 3.0,我有下面的方法,它正确返回指定目录的所有文件和目录(和子目录)的集合。如果可能的话,我想把它简化为仅使用我非常熟悉的结构。具体来说,以下是我不清楚的事情:

1. IEnumerable<FileSystemInfo>: I'd like to return List<FileSystemInfo> instead
2. Stack<FileSystemInfo>: I'd list to use List<FileSystemInfo> instead.
3. yield return: I've never used this before

public static IEnumerable<FileSystemInfo> GetAllFilesAndDirectories ( string dir ) {

    DirectoryInfo dirInfo = new DirectoryInfo( dir );
    Stack<FileSystemInfo> stack = new Stack<FileSystemInfo>();

    stack.Push( dirInfo );
    while ( dirInfo != null || stack.Count > 0 ) {
        FileSystemInfo fileSystemInfo = stack.Pop();
        DirectoryInfo subDirectoryInfo = fileSystemInfo as DirectoryInfo;
        if ( subDirectoryInfo != null ) {
            yield return subDirectoryInfo;
            foreach ( FileSystemInfo fsi in subDirectoryInfo.GetFileSystemInfos() ) {
                stack.Push( fsi );
            }
            dirInfo = subDirectoryInfo;
        } else {
            yield return fileSystemInfo;
            dirInfo = null;
        }
    }

}

可以说我应该对上面的代码感到满意,但这不是我今天拍摄的内容。

提前致谢

6 个答案:

答案 0 :(得分:2)

这是我能想到的最短路:

static List<FileSystemInfo> GetAllFilesAndDirectories(string dir)
{
    DirectoryInfo dirInfo = new DirectoryInfo(dir);            
    List<FileSystemInfo> allFilesAndDirectories = new List<FileSystemInfo>();

    allFilesAndDirectories.AddRange(dirInfo.GetFiles("*", SearchOption.AllDirectories));
    allFilesAndDirectories.AddRange(dirInfo.GetDirectories("*", SearchOption.AllDirectories));

    return allFilesAndDirectories;
}

它将从给定路径开始返回所有级别的所有文件和目录的列表。它返回的顺序是所有文件,然后是所有目录。

答案 1 :(得分:1)

我相信您正在寻找现有方法GetFileSystemInfos(string,SearchOptions)。如果将AllDirectories指定为SearchOptions值,它将递归搜索传入的文件夹。

例如:

public static List<FileSystemInfo> GetAllFilesAndDirectories ( string dir ) {
  DirectoryInfo info = new DirectoryInfo(dir);
  FileSystemInfo[] all = info.GetFileSystemInfos("*", SearchOptions.AllDirectories);
  return new List<FileSystemInfo>(all);
}

如果你想做很多事情,尽管你可以做到以下

public static List<FileSystemInfo> GetAllFilesAndDirectories ( string dir ) {
  int i = 0; 
  List<DirectoryInfo> toProcess = new List<DirectoryInfo>();
  List<FileSystemInfo> list = new List<FileSystemInfo>();
  toProcess.Add(new DirectoryInfo(dir));
  while ( i < toProcess.Count ) { 
    DirectoryInfo curDir = toProcess[i];
    foreach ( FileSystemInfo curFile in curDir.GetFileSystemInfos() ) {
      list.Add(curFile);
      DirectoryInfo maybe = curFile as DirectoryInfo;
      if ( maybe != null ) {
        toProcess.Add(maybe);
      }
    i++;
  }
  return list;
}

  FileSystemInfo[] all = info.GetFileSystemInfos("*", SearchOptions.AllDirectories);
  return new List<FileSystemInfo>(all);
}

答案 2 :(得分:1)

    public List<Object> GetFilesAndDirectories(string path)
    {
        List<Object> lst = new List<Object>();
        string[] dirs = null;

        try
        {
            dirs = Directory.GetDirectories(path);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

        foreach (string d in dirs)
        {
            string[] files = null;

            try
            {
                files = Directory.GetFiles(d);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            foreach (string f in files)
            {
                lst.Add(f);
            }

            lst.Add(d);

            lst.AddRange(GetFilesAndDirectories(d));
        }

        return lst;
    }


List<Object> stuff = GetFilesAndDirectories(someRoot);

答案 3 :(得分:0)

你曾经特别要求“愚蠢地”。我认为其他两个答案非常好,但是这是另一种方法,在开始级代码中使用更基本,易于理解的方式。

http://support.microsoft.com/kb/303974

修改

我知道这不是3.0,但它仍然是经过尝试,测试和易于理解的方式。

答案 4 :(得分:0)

如果你想要一个“初学者友好的方法”,我可以建议bobbymcr method

但是,如果你想保留你的代码结构,我会重现我在your following question中发布的代码:

static IEnumerable<FileSystemInfo> GetAllFilesAndDirectories(string path)
{
    string currentDirectory = "";
    string[] files = Directory.GetFiles( // skip empty subfolders
        path, "*.*", SearchOption.AllDirectories);
    foreach (string file in files)
    {
        if(currentDirectory != Path.GetDirectoryName(file))
        {
            // First time in this directory: return it
            currentDirectory = Path.GetDirectoryName(file);
            yield return new DirectoryInfo(currentDirectory);
        }

        yield return new FileInfo(file);
    }
}

答案 5 :(得分:0)

我认为从代码可读性的角度来看,最好的办法就是编写一个递归函数。递归函数是一个自我调用函数,直到它到达不需要调用任何其他函数的点。

为了说明,n的阶乘,写成n!并且定义为1 x 2 x 3 x ... x n(其中n是正整数)的数量可以很容易地以递归方式定义,如下所示。

public int factorial(int n)
{
    if (n < 0)
    {
        throw new Exception("A factorial cannot be calculated for negative integers.");
    }

    if (n == 0 || n == 1)
    {
        // end condition, where we do not need to make a recursive call anymore
        return 1;
    }
    else
    {
        // recursive call
        return n * factorial(n - 1);
    }
}

注意:0!和1!被定义为1。

同样,也可以递归地定义枚举给定路径下的所有文件和文件夹的方法。这是因为文件和文件夹具有递归结构。

因此,如下所述的方法可行:

public static List<FileSystemInfo> GetAllFilesAndFolders(string folder)
{
    // NOTE : We are performing some basic sanity checking
    // on the method's formal parameters here
    if (string.IsNullOrEmpty(folder))
    {
        throw new ArgumentException("An empty string is not a valid path.", "folder");
    }
    if (!Directory.Exists(folder))
    {
        throw new ArgumentException("The string must be an existing path.", "folder");
    }

    List<FileSystemInfo> fileSystemInfos = new List<FileSystemInfo>();

    try
    {
        foreach (string filePath in Directory.GetFiles(folder, "*.*"))
        {
            // NOTE : We will add a FileSystemInfo object for each file found
            fileSystemInfos.Add(new FileInfo(filePath));
        }
    }
    catch
    {
        // NOTE : We are swallowing all exceptions here
        // Ideally they should be surfaced, and at least logged somewhere
        // Most of these will be security/permissions related, i.e.,
        // the Directory.GetFiles method will throw an exception if it
        // does not have security privileges to enumerate files in a folder.
    }
    try
    {
        foreach (string folderPath in Directory.GetDirectories(folder, "*"))
        {
            // NOTE : We will add a FileSystemInfo object for each directory found
            fileSystemInfos.Add(new DirectoryInfo(folderPath));

            // NOTE : We will also add all FileSystemInfo objects found under
            // each directory we find
            fileSystemInfos.AddRange(GetAllFilesAndFolders(folderPath));
        }
    }
    catch
    {
        // NOTE : We are swallowing all exceptions here
        // Ideally they should be surfaced, and at least logged somewhere
        // Most of these will be security/permissions related, i.e.,
        // the Directory.GetDirectories method will throw an exception if it
        // does not have security privileges to enumerate files in a folder.
    }

    return fileSystemInfos;
}

需要注意的一点是,此方法将“遍历”文件夹下的整个目录结构,并且在“走完”整个层次结构之前不会返回。因此,如果要找到很多对象,可能需要很长时间才能返回。

另外需要注意的是,使用Lambda表达式和扩展方法可以进一步提高此方法的可读性。

注意:使用Directory.GetFiles和Directory.GetDirectories来递归子文件夹的麻烦在于,如果抛出任何异常(例如,与安全权限相关),该方法将不返回任何内容,而手动递归则允许人们处理那些例外,仍然会得到一组文件。