代码之家  ›  专栏  ›  技术社区  ›  dassouki

初学者-C#通过目录迭代生成文件列表

  •  1
  • dassouki  · 技术社区  · 16 年前

    最终的目标是拥有某种形式的数据结构,该结构存储一个目录的层次结构,该目录将存储在一个txt文件中。

    我正在使用下面的代码,到目前为止,我正在努力组合dir、subdir和文件。

    /// <summary>
    /// code based on http://msdn.microsoft.com/en-us/library/bb513869.aspx
    /// </summary>
    /// <param name="strFolder"></param>
    public static void TraverseTree ( string strFolder )
    {
      // Data structure to hold names of subfolders to be
      // examined for files.
      Stack<string> dirs = new Stack<string>( 20 );
    
      if ( !System.IO.Directory.Exists( strFolder ) )
      {
        throw new ArgumentException();
      }
      dirs.Push( strFolder );
    
      while ( dirs.Count > 0 )
      {
        string currentDir = dirs.Pop();
        string[] subDirs;
        try
        {
          subDirs = System.IO.Directory.GetDirectories( currentDir );
        }
    
        catch ( UnauthorizedAccessException e )
        {
          MessageBox.Show( "Error: " + e.Message );
          continue;
        }
        catch ( System.IO.DirectoryNotFoundException e )
        {
          MessageBox.Show( "Error: " +  e.Message );
          continue;
        }
    
        string[] files = null;
        try
        {
          files = System.IO.Directory.GetFiles( currentDir );
        }
    
        catch ( UnauthorizedAccessException e )
        {
          MessageBox.Show( "Error: " +  e.Message );
          continue;
        }
    
        catch ( System.IO.DirectoryNotFoundException e )
        {
          MessageBox.Show( "Error: " + e.Message );
          continue;
        }
        // Perform the required action on each file here.
        // Modify this block to perform your required task.
        /*
        foreach ( string file in files )
        {
          try
          {
            // Perform whatever action is required in your scenario.
            System.IO.FileInfo fi = new System.IO.FileInfo( file );
            Console.WriteLine( "{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime );
          }
          catch ( System.IO.FileNotFoundException e )
          {
            // If file was deleted by a separate application
            //  or thread since the call to TraverseTree()
            // then just continue.
            MessageBox.Show( "Error: " +  e.Message );
            continue;
          }
        } 
        */
    
        // Push the subdirectories onto the stack for traversal.
        // This could also be done before handing the files.
        foreach ( string str in subDirs )
          dirs.Push( str );
    
        foreach ( string str in files )
          MessageBox.Show( str );
      }
    
    5 回复  |  直到 16 年前
        1
  •  8
  •   Valera Kolupaev    16 年前

    你可以用一种 Composite pattern 其中,复合项-是一个文件夹。

    下面是一个示例代码,用于构建目标文件夹的树结构。它递归地工作,并且消耗更多的内存,但是简单性值得。

    class TreeItem
    {
        public string FolderName;
        public List<TreeItem> SubFolders = new List<TreeItem>();
        public string[] Files;
    }
    
    class Program
    {
    
        private static TreeItem FileTree(string rootFolder){
            var item = new TreeItem();
            item.FolderName = rootFolder;
            item.Files = System.IO.Directory.GetFiles(rootFolder);
    
            foreach(var folder in System.IO.Directory.GetDirectories(rootFolder))
            {
                item.SubFolders.Add(FileTree(folder));
            }
            return item;
        }
    
        //Traversal algorithm
        private static void PrintComposite(TreeItem node, int ident)
        {
            var dirName = System.IO.Path.GetFileName(node.FolderName);
            Console.WriteLine(@"{0}{1}", new string('-', ident), dirName);
            foreach(var subNode in node.SubFolders)
            {
                PrintComposite(subNode, ident + 1);
            }
        }
    
        public static void Main(string[] args)
        {
            var tree = FileTree(@"D:\Games");
            PrintComposite(tree,0);
        }   
    }
    
        2
  •  1
  •   verisimilidude    16 年前

    首先,我认为你需要制造更多的物体。DirectoryElementInterface接口或抽象类、DirectoryElement对象以及实现DirectoryElementInterface的FileElement对象。现在,与其使用堆栈来迭代继承权,不如创建 DirectoryElementInterface root = new DirectoryElement(nameOfNode) . 然后对于getFiles中的每个文件 root.addElement(new FileElement(filename)); . addElement应该添加到DirectoryElement中的列表中。对目录执行类似的操作。好了,现在你可以创建一个级别了。

    root 一个参数。你可以称之为任何东西,但对于这个讨论,我将称这个新的例程为addDirectoryInformation。现在您的主要任务是创建根目录并调用addDirectoryInformation传入根目录。要进行迭代,我们需要向现在填充的根请求元素列表,对列表执行foreach操作,并为目录中的每个元素调用addDirectoryInformation。一旦你有工作,移动循环到addDirectoryInformation的结尾。现在,您添加的每个目录都递归地添加其所有子目录。

    对于一个正确的递归程序来说还有一件事。你必须知道什么时候停止循环。在这种情况下很容易。如果列表中没有目录,则不会调用addDirectoryInformation。所以你完了。

        3
  •  0
  •   dassouki    16 年前

    http://weblogs.asp.net/israelio/archive/2004/06/23/162913.aspx

    // How much deep to scan. (of course you can also pass it to the method)
    const int HowDeepToScan=20;
    
    public static void ProcessDir ( string dirName, int recursionLvl, string strFileName)
    {
    
      string tabs = new String( '-', recursionLvl );
    
      if ( recursionLvl<=HowDeepToScan )
      {
        // Process the list of files found in the directory. 
        string [] fileEntries = Directory.GetFiles( dirName );
        TextWriter tw = new StreamWriter( strFileName, true );
        tw.WriteLine( tabs + "<a href=\" " +  System.IO.Path.GetFullPath( dirName ) + "\">" + System.IO.Path.GetFileName( dirName ) + "</a><br />" );
        foreach ( string fileName in fileEntries )
        {
          // do something with fileName
    
          tw.WriteLine( tabs + "<a href=\" " +  System.IO.Path.GetFullPath( fileName ) + "\">" + System.IO.Path.GetFileName( fileName ) + "</a><br />" );
    
        }
        tw.Close();
    
        // Recurse into subdirectories of this directory.
        string [] subdirEntries = Directory.GetDirectories( dirName );
        foreach ( string subdir in subdirEntries )
          // Do not iterate through reparse points
          if ( ( File.GetAttributes( subdir ) &
            FileAttributes.ReparsePoint ) !=
                FileAttributes.ReparsePoint )
    
            ProcessDir( subdir, recursionLvl+1, strFileName );
    
      }
    }
    

    输出

    <a href=" C:\code">code</a><br />
    <a href=" C:\code\group.zip">FluentPath (1).zip</a><br />
    <a href=" C:\code\index.html">index.html</a><br />
    
        4
  •  0
  •   Stephen Murby    16 年前

    上周我做了一个课程,在那里我们做了类似的事情,输出是到控制台,但没有理由你不能把它写到一个.txt文件。

    使用System.Linq; 使用System.Text;

    命名空间ShowDirectory { { 静态void Main(字符串[]args) { System.IO.DirectoryInfo dir=新建System.IO.DirectoryInfo(@“C:\”); foreach(dir.GetFiles(“ ")) { Console.WriteLine(“{0},{1}”,file.Name,file.Length); } Console.ReadLine(); } } }

        5
  •  0
  •   Maxim Vasiliev    13 年前

    其中一种方法是对文件树使用迭代器,如下所示:

    // IncludeExcludeFileEnumerator(string baseDir, string includePattern, string excludePattern)
    // Include pattern can include ** that means tree hierarchy
    var myFiles = new IncludeExcludeFileEnumerable(@"C:\test\aaa", @"**.bmp,*.jpg", "*excl_bad*.*,*fu*");
    foreach (var s in myFiles)
    {
        Console.Out.WriteLine(s);
    }
    

    文件迭代器(IEnumerator,IEnumerable)的代码:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text.RegularExpressions;
    
    namespace IncludeExcludeFileEnumerator
    {
        public class IncludeExcludeFileEnumerator : IEnumerator<String>
        {
            private string excludeRegExPattern;
            private readonly Regex regexSeparateFilePath;
            private readonly Regex excludeRegex = null;
            private int currentPatternIndex;
            private IEnumerator<string> filesEnum;
            private IEnumerable<string> files;
            bool isNext = true;
            private readonly List<Tuple<string, string, SearchOption>> incPatternsList;
    
    
            public IncludeExcludeFileEnumerator(string baseDirectory, string includePattern, string excludePattern)
            {
                // Split comma separated string to array of include patterns
                var initIncludePatterns = includePattern.Split(',');
                regexSeparateFilePath = new Regex(@"(.*)[\\/]([^\\/]*$)", RegexOptions.Compiled);
    
                // Prepare include patterns
                incPatternsList = initIncludePatterns.ToList().ConvertAll(
                    (incPattern) =>
                    {
                        incPattern = incPattern.Trim();
                        var matches = regexSeparateFilePath.Matches(incPattern);
                        string pathPattern;
                        string filePattern;
                        if (matches.Count == 0)
                        {
                            pathPattern = "";
                            filePattern = incPattern;
                        }
                        else
                        {
                            pathPattern = matches[0].Groups[1].Value;
                            filePattern = matches[0].Groups[2].Value;
                        }
                        SearchOption searchOption = SearchOption.TopDirectoryOnly;
                        if (filePattern.Contains("**"))
                        {
                            filePattern = filePattern.Replace("**", "*");
                            searchOption = SearchOption.AllDirectories;
                        }
                        var fullPathPattern = Path.Combine(baseDirectory, pathPattern);
                        // Returns tuple {PathPattern, FilePattern, SearchOption}
                        return new Tuple<string, string, SearchOption>(fullPathPattern, filePattern, searchOption);
                    });
    
                // Prepare regular expression for exclude case (all in one, concatinated by (| - or) separator)
                if (!String.IsNullOrWhiteSpace(excludePattern))
                {
                    var excPatterns = excludePattern.Replace(".", @"\.");
                    excPatterns = excPatterns.Replace("*", ".*");
                    excludeRegExPattern = excPatterns.Replace(",", "|");
                    excludeRegex = new Regex(excludeRegExPattern, RegexOptions.Compiled);
                }
                Reset();
            }
    
            public string Current
            {
                get { return filesEnum.Current; }
            }
    
            public void Dispose()
            {
    
            }
    
            object System.Collections.IEnumerator.Current
            {
                get { return (Object)this.Current; }
            }
    
            public bool MoveNext()
            {
                do
                {
                    if (( filesEnum == null ) && (incPatternsList.Count < currentPatternIndex + 2))
                    {
                        return false;
                    }
                    if ((filesEnum == null) || (isNext == false))
                    {
                        var tuple = incPatternsList[++currentPatternIndex];
                        files = Directory.EnumerateFiles(tuple.Item1, tuple.Item2, tuple.Item3);
                        filesEnum = files.GetEnumerator();
                        isNext = true;
                    }
                    while (isNext)
                    {
                        isNext = filesEnum.MoveNext();
                        if (isNext) 
                        {
                            if (excludeRegex==null) return true;
                            if (!excludeRegex.Match(filesEnum.Current).Success) return true;
                            // else continue;
                        }
                        else
                        {
                            filesEnum = null;
                        }
                    }
                } while (true);
            }
    
            public void Reset()
            {
                currentPatternIndex = -1;
                filesEnum = null;
            }
        }
    
        public class IncludeExcludeFileEnumerable : IEnumerable<string>
        {
            private string baseDirectory;
            private string includePattern;
            private string excludePattern;
    
            public IncludeExcludeFileEnumerable(string baseDirectory, string includePattern, string excludePattern)
            {
                this.baseDirectory = baseDirectory;
                this.includePattern = includePattern;
                this.excludePattern = excludePattern;
            }
    
            public IEnumerator<string> GetEnumerator()
            {
                return new IncludeExcludeFileEnumerator(baseDirectory, includePattern, excludePattern);
            }
    
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return (IEnumerator)this.GetEnumerator();
            }
        }
    }
    
    推荐文章