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

C# 初学者-C通过目录迭代生成一个文件列表,c#,file-structure,C#,File Structure,最终目标是获得某种形式的数据结构,该数据结构存储要存储在txt文件中的目录的层次结构 我正在使用下面的代码,到目前为止,我正在努力组合dir、subdir和文件 /// <summary> /// code based on http://msdn.microsoft.com/en-us/library/bb513869.aspx /// </summary> /// <param name="strFolder"></param> public

最终目标是获得某种形式的数据结构,该数据结构存储要存储在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 );
  }
您可以使用一种类型,其中复合项是一个文件夹

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

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);
    }   
}
您可以使用一种类型,其中复合项是一个文件夹

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

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);
    }   
}

首先,我认为你需要制造更多的物体。DirectoryElementInterface接口或抽象类、DirectoryElement对象以及实现DirectoryElementInterface的FileElement对象。现在,创建DirectoryElementInterface root=new DirectoryElementnameOfNode,而不是使用堆栈遍历继承者权限。然后对getFiles中的每个文件执行类似于root.addlementNew FileElementfilename;的操作;。addElement应添加到DirectoryElement内的列表中。对目录执行类似的操作。好的,现在您可以创建一个级别

现在进入迭代步骤。以您刚刚编写的例程为例,将root作为一个参数。你可以把它叫做任何东西,但对于这次讨论,我将把这个新的例程叫做addDirectoryInformation。现在,您的主要任务是创建根目录并调用addDirectoryInformation传入根目录。要进行迭代,我们需要向现在已填充的根请求其元素列表,对该列表执行foreach,并为作为目录的每个元素调用addDirectoryInformation。完成该操作后,将循环移动到addDirectoryInformation的末尾。现在,您添加的每个目录都会递归地添加其所有子目录


正确的递归程序还有一件事。您必须知道何时停止递归。在这种情况下很容易。如果列表中没有目录,则不会调用addDirectoryInformation。你已经完成了。

首先,我认为你需要制作更多的对象。DirectoryElementInterface接口或抽象类、DirectoryElement对象以及实现DirectoryElementInterface的FileElement对象。现在,创建DirectoryElementInterface root=new DirectoryElementnameOfNode,而不是使用堆栈遍历继承者权限。然后对getFiles中的每个文件执行类似于root.addlementNew FileElementfilename;的操作;。addElement应添加到DirectoryElement内的列表中。对目录执行类似的操作。好的,现在您可以创建一个级别

现在进入迭代步骤。以您刚刚编写的例程为例,将root作为一个参数。你可以把它叫做任何东西,但对于这次讨论,我将把这个新的例程叫做addDirectoryInformation。现在,您的主要任务是创建根目录并调用addDirectoryInformation传入根目录。要进行迭代,我们需要向现在已填充的根请求其元素列表,对该列表执行foreach,并为作为目录的每个元素调用addDirectoryInformation。完成该操作后,将循环移动到addDirectoryInformation的末尾。现在,您添加的每个目录都会递归地添加其所有子目录


正确的递归程序还有一件事。您必须知道何时停止递归。在这种情况下很容易。如果列表中没有目录,则不会调用addDirectoryInformation。这样就完成了。

我使用基于

输出


我使用基于

输出


上周我做了一个课程,我们做了一些类似的事情,输出是控制台,但没有理由不能将其写入.txt文件

使用制度; 使用System.Collections.Generic; 使用System.Linq; 使用系统文本

命名空间显示目录 { 班级计划 { 静态环[]args { Console.WriteLineth此程序列出目录中的所有文件。; System.IO.DirectoryInfo dir=新的System.IO。DirectoryInfo@C:\; dir.GetFiles中的foreach System.IO.FileInfo文件。 { Console.WriteLine{0},{1},file.Name,file.Length; } Console.ReadLine; } }
}

上周我上了一门课,我们做了类似的事情,输出到控制台,但没有理由不能将其写入.txt文件

使用制度; 使用System.Collections.Generic; 使用System.Linq; 使用系统文本

命名空间显示目录 { 班级计划 { 静态环[]args { Console.WriteLineth此程序列出目录中的所有文件。; System.IO.DirectoryInfo dir=新的System.IO。DirectoryInfo@C:\; dir.Get中的foreach System.IO.FileInfo文件 文件夹。 { Console.WriteLine{0},{1},file.Name,file.Length; } Console.ReadLine; } }
}其中一种方法是在文件树上使用迭代器,如下所示:

// 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();
        }
    }
}

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

// 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();
        }
    }
}

我想你得更清楚地说明你的问题。代码乍一看很好。顺便说一句,该算法使用显式堆栈进行迭代,而不是递归。不要害怕递归!我真的不明白你想干什么。然而,你的问题让我想起了我最近看到的一个叫Fluent Path的酷项目:我认为你必须更清楚地陈述你的问题。代码乍一看很好。顺便说一句,该算法使用显式堆栈进行迭代,而不是递归。不要害怕递归!我真的不明白你想干什么。然而,你的问题让我想起了我最近看到的一个叫Fluent Path的酷项目:最初的任务有点不清楚,这样的复杂性不是很简单吗?复合模式旨在帮助统一一致地处理每个节点和叶,但现在,它不是必需的。最初的任务有点不清楚,这样的复杂性不是很简单吗?复合模式的设计有助于统一一致地处理每个节点和叶子,但现在不需要了;但是,我还想将文件添加到列表中,我一直在使用printnode并添加另一个foreach,我将看看是否可以让它工作。。到目前为止,这是伟大的,他的作品非常优秀;但是,我还想将文件添加到列表中,我一直在使用printnode并添加另一个foreach,我将看看是否可以让它工作。。到目前为止,这是伟大的