在多个文件夹上返回文件列表的最有效方法

时间:2011-08-02 16:06:26

标签: c# model-view-controller recursion

大家好我已经得到了以下代码,当匹配某些条件时,它将从路径目录中获取所有文件,包括子目录。目前我有两种方法;一个去获取所有文件并将它们添加到List,然后另一个方法返回List。只是想知道这是否是最好的方法,还是将两者结合起来更有效率?或者我的代码可以重写以提高效率吗?对不起,我对这一切都很陌生!

public class FileUtility
    {
        List<FileInfo> fileInfoList = new List<FileInfo>();

        public void ProcessDir(string sourceDir, String userName)
        {
            try
            {
                string userNameFirstLetter = userName.First().ToString();
                DirectoryInfo di = new DirectoryInfo(sourceDir);

                foreach (FileInfo fi in di.GetFiles())
                {
                    if (fi.Extension == ".xls" || fi.Extension == ".xlsx" || fi.Extension == ".pdf")
                    {
                        if (fi.Name.Contains(userName))
                        {
                            if (fi.Name.Contains("X"))
                            {
                                if(fi.Name.First().ToString().Equals(userNameFirstLetter))
                                {
                                    if (fi.Name.Split(Convert.ToChar("X"))[0].Equals(userName))
                                    {
                                        fileInfoList.Add(fi);
                                    }
                                }
                            }
                        }
                    }
                }

                // Recurse into subdirectories of this directory.
                string[] subdirEntries = Directory.GetDirectories(sourceDir);
                foreach (string subdir in subdirEntries)
                {
                    // Do not iterate through reparse points
                    if ((File.GetAttributes(subdir) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint)
                    {
                        ProcessDir(subdir, userName);
                    }
                }
            }
            catch (DirectoryNotFoundException exp)
            {
                throw new DirectoryNotFoundException("Directory not found " + exp.Message);
            }
            catch (IOException exp)
            {
                throw new IOException("The Process cannot access the file because it is in use by another process " + exp.Message);
            }
        }

        public List<FileInfo> GetFileInfoList()
        {
            return fileInfoList;
        }
}

5 个答案:

答案 0 :(得分:5)

您不需要递归。

string[] filePaths = Directory.GetFiles(@"c:\SomeDir\", "*.ext", SearchOption.AllDirectories);

答案 1 :(得分:2)

您可以这样做:

DirectoryInfo dir = new DirectoryInfo(@"C:\PathName");
IEnumerable<FileInfo> files = dir.GetFiles("*.*");

然后,如果您使用的是C#3.5或更高版本,我可以使用LINQ对其进行过滤。类似的东西:

// Only use files with userName in the filename
files = files.Where(f => f.Name.Contains(userName));

或者结合2:

DirectoryInfo dir = new DirectoryInfo(@"C:\PathName");
IEnumerable<FileInfo> files = dir.GetFiles("*.*").Where(f => f.Name.Contains(userName));

答案 2 :(得分:0)

如果这是关于获取文件列表,请查看Paul Alan Taylor的答案。

如果你想学习(有点)递归:直接从ProcessDir方法返回文件列表。

使用您提供的代码,至少需要调用,并且容易出错。特别是如果该类被重用。

我在代码中更改了一些内容:

  1. fileInfoList在ProcessDir
  2. 中声明
  3. 递归调用将结果添加到“当前”结果。

    公共类FileUtility     {

        public List<FileInfo> ProcessDir(string sourceDir, String userName)
        {
            List<FileInfo> fileInfoList = new List<FileInfo>();
    
            try
            {
                string userNameFirstLetter = userName.First().ToString();
                DirectoryInfo di = new DirectoryInfo(sourceDir);
    
                foreach (FileInfo fi in di.GetFiles())
                {
                    if (fi.Extension == ".xls" || fi.Extension == ".xlsx" || fi.Extension == ".pdf")
                    {
                        if (fi.Name.Contains(userName))
                        {
                            if (fi.Name.Contains("X"))
                            {
                                if(fi.Name.First().ToString().Equals(userNameFirstLetter))
                                {
                                    if (fi.Name.Split(Convert.ToChar("X"))[0].Equals(userName))
                                    {
                                        fileInfoList.Add(fi);
                                    }
                                }
                            }
                        }
                    }
                }
    
                // Recurse into subdirectories of this directory.
                string[] subdirEntries = Directory.GetDirectories(sourceDir);
                foreach (string subdir in subdirEntries)
                {
                    // Do not iterate through reparse points
                    if ((File.GetAttributes(subdir) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint)
                    {
                        fileInfoList.AddRange(ProcessDir(subdir, userName));
                    }
                }
            }
            catch (DirectoryNotFoundException exp)
            {
                throw new DirectoryNotFoundException("Directory not found " + exp.Message);
            }
            catch (IOException exp)
            {
                throw new IOException("The Process cannot access the file because it is in use by another process " + exp.Message);
            }
    
            return fileInfoList;
        }
    

    }

  4. 注意:您的代码可以改进,例如通过使用“逻辑和”if组合&&语句。

答案 3 :(得分:0)

有一种更有效的方法。

string[] filePaths = Directory.GetFiles(rootDirectory,searchPattern,SearchOption.AllDirectories);

您需要修改searchPattern以涵盖选择文件的条件。

AFAIK,searchPattern的操作方式与正则表达式类似。

或者,您可以获取与某些文件扩展名匹配的所有文件,然后循环浏览它们以按您的条件过滤它们

答案 4 :(得分:0)

您可能不需要该类的实例。考虑将其设为静态,如下所示:

  public static class FileUtility
  {
    private static void ProcessDir(string sourceDir, String userName, List<FileInfo> fileInfoList)
    {
        try
        {
            string userNameFirstLetter = userName.First().ToString();
            DirectoryInfo di = new DirectoryInfo(sourceDir);

            foreach (FileInfo fi in di.GetFiles())
            {
                if ((fi.Extension == ".xls" || fi.Extension == ".xlsx" || fi.Extension == ".pdf")
                    && fi.Name.Contains(userName) && fi.Name.Contains("X")
                    && fi.Name.First().ToString().Equals(userNameFirstLetter)
                    && fi.Name.Split(Convert.ToChar("X"))[0].Equals(userName))
                 {
                    fileInfoList.Add(fi);
                 }
            }

            // Recurse into subdirectories of this directory.
            string[] subdirEntries = Directory.GetDirectories(sourceDir);
            foreach (string subdir in subdirEntries)
            {
                // Do not iterate through reparse points
                if ((File.GetAttributes(subdir) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint)
                {
                    ProcessDir(subdir, userName, fileInfoList);
                }
            }
        }
        catch (DirectoryNotFoundException exp)
        {
            throw new DirectoryNotFoundException("Directory not found " + exp.Message);
        }
        catch (IOException exp)
        {
            throw new IOException("The Process cannot access the file because it is in use by another process " + exp.Message);
        }
    }

    public static List<FileInfo> GetFileInfoList(string sourceDir, string userName)
    {
        List<FileInfo> fileInfoList = new List<FileInfo>();
        ProcessDir(sourceDir, userName, fileInfoList);
        return fileInfoList;
    }
  }

此外,您可以通过&&和标准一起使其更简洁。