【问题标题】:c# How to iterate through the file system and assign numberingc#如何遍历文件系统并分配编号
【发布时间】:2014-09-23 07:29:21
【问题描述】:

我遇到了一个问题。

我想遍历本地 PC 文件夹,包括目录,并针对文件系统层次结构中的每个文件夹计算编号系统。

根文件夹应计算为 1,2,3 等。

如果文件夹 1 中有三个子文件夹,则计算出的数字应为: 1.1、1.2、1.3

如果上面的子文件夹中有三个子文件夹,那么计算出来的数字应该是: 1.1.1、1.1.2、1.1.3

如果文件夹二(根文件夹)中有三个子文件夹,则计算的数字应为: 2.1、2.2、2.3

或者换一种说法:

 1   Root Folder 
 1.1   Root Sub Folder 1
 1.1.1   Sub Folder
 1.1.2     Sub Folder
 1.2 Root Sub Folder 2
 1.2.1 List item
 1.2.2   List item 

等等。等等

然后应该将此逻辑应用于所有文件夹和子文件夹。

输出示例

1.1.1 | "c:\Root\Folder1\Folder1\"

到目前为止,我在某些情况下似乎可以正常工作,但在其他情况下可能会失败:

    private string rootpath = @"C:\FolderHierarchy\";
    private string FolderSequenceCountBase = "";
    private int CurrentRootPathCount = 0;
    private int Counter = 0;

    private void CalculateFolderHierarchyNumbers()
    {
        //Get First List of Folders
        string[] Dirs = Directory.GetDirectories(rootpath, "*.*", SearchOption.TopDirectoryOnly);

        for (int i = 0; i < Dirs.Count(); i++)
        {
            FolderSequenceCountBase = (i + 1).ToString();
            CurrentRootPathCount = i + 1;
            Console.WriteLine("Processed folder '{0}'.", Dirs[i] + " = " + (i + 1));                
            GetSubDirs(Dirs[i]);
        }
    }

    private void GetSubDirs(string item)
    {
        //Get next list of folders in the folder hierarchy
        string[] SubDirs = Directory.GetDirectories(item, "*.*", SearchOption.TopDirectoryOnly);
        foreach (var DirPath in SubDirs)
        {
            //Increment count of folders within the current folder list
            Counter += 1;
            Console.WriteLine("Processed folder '{0}'.", DirPath + " = " + FolderSequenceCountBase + "." + Counter);
        }

        Counter = 0;

        //Get next list of folders in the folder hierarchy
        foreach (var DirPath in SubDirs)
        {
            FolderSequenceCountBase += ".1";
            GetSubDirs(DirPath);  
        }
    }

希望这很清楚。

谢谢 瑞克

【问题讨论】:

  • 您的意思是要提取每个文件夹中的数字吗?您还应该展示您之前为解决问题所做的任何尝试
  • 目录或文件是否总是以数字结尾?如果没有怎么办?
  • 我理解正确吗,您知道如何遍历目录,...但是在将数字放在那里时遇到麻烦? (如果您还将用于遍历的代码发布到您的问题中,那就太好了)。 @TimSchmelter 根据我的理解,Folder1、Folder2、...只是示例名称,文件夹名称/文件名中的数字只是巧合,与他想要做的编号无关
  • (但如果 rick450d 也能明确这一点或发布是否是这种情况以及定义特定文件夹/文件获得哪个编号的内容会很好[仅订购内部目录或其他内容)
  • 只需在“listfolder”和“listfiles”函数中添加一个额外的字符串参数。 --> 完成

标签: c# list filesystems


【解决方案1】:

所以你想找到一个文件并获取它在 of 目录中的编号以及它的所有父目录?因为我发现它很有趣,所以我从头开始写了一些东西。请注意,它目前尚未经过测试,但无论如何它可能会给您一个想法:

public static IEnumerable<FileEntryInfo> EnumerateFindFiles(string fileToFind, StringComparison comparison = StringComparison.CurrentCultureIgnoreCase, DirectoryInfo rootDir = null, string[] drivesToSearch = null)
{
    IEnumerable<FileEntryInfo> foundEntries = Enumerable.Empty<FileEntryInfo>();
    if (rootDir != null && drivesToSearch != null)
        throw new ArgumentException("Specify either the root-dir or the drives to search, not both");
    else if (rootDir != null)
    {
        foundEntries = EnumerateFindEntryRoot(fileToFind, rootDir, comparison);
    }
    else
    {
        if (drivesToSearch == null) // search the entire computer
            drivesToSearch = System.Environment.GetLogicalDrives();
        foreach (string dr in drivesToSearch)
        {
            System.IO.DriveInfo di = new System.IO.DriveInfo(dr);

            if (!di.IsReady)
            {
                Console.WriteLine("The drive {0} could not be read", di.Name);
                continue;
            }
            rootDir = di.RootDirectory;
            foundEntries = foundEntries.Concat(EnumerateFindEntryRoot(fileToFind, rootDir, comparison));
        }
    }
    foreach (FileEntryInfo entry in foundEntries)
        yield return entry;
}

public class FileEntryInfo
{
    public FileEntryInfo(string path, int number)
    {
        this.Path = path;
        this.Number = number;
    }
    public int Number { get; set; }
    public string Path { get; set; }
    public FileEntryInfo Root { get; set; }

    public IEnumerable<int> GetNumberTree()
    {
        Stack<FileEntryInfo> filo = new Stack<FileEntryInfo>();
        FileEntryInfo entry = this;
        while (entry.Root != null)
        {
            filo.Push(entry.Root);
            entry = entry.Root;
        }
        while(filo.Count > 0)
            yield return filo.Pop().Number;
        yield return this.Number; 
    }


    public override bool Equals(object obj)
    {
        FileEntryInfo fei = obj as FileEntryInfo;
        if(obj == null) return false;
        return Number == fei.Number && Path == fei.Path;
    }

    public override int GetHashCode()
    {
        return Path.GetHashCode();
    }

    public override string ToString()
    {
        return Path;
    }
}

private static IEnumerable<FileEntryInfo> EnumerateFindEntryRoot(string fileNameToFind, DirectoryInfo rootDir, StringComparison comparison = StringComparison.CurrentCultureIgnoreCase)
{
    Queue<FileEntryInfo> queue = new Queue<FileEntryInfo>();
    FileEntryInfo root = new FileEntryInfo(rootDir.FullName, 1);
    queue.Enqueue(root);

    while (queue.Count > 0)
    {
        FileEntryInfo fe = queue.Dequeue();
        List<FileEntryInfo> validFiles = new List<FileEntryInfo>();
        try
        { // you cannot yield from try-catch, hence this approach
            FileAttributes attr = File.GetAttributes(fe.Path);
            //detect whether its a directory or file
            bool isDirectory = (attr & FileAttributes.Directory) == FileAttributes.Directory;
            if (isDirectory)
            {
                int entryCount = 0;
                foreach (string entry in Directory.EnumerateFileSystemEntries(fe.Path))
                {
                    entryCount++;
                    FileEntryInfo subEntry = new FileEntryInfo(entry, entryCount);
                    subEntry.Root = fe;
                    queue.Enqueue(subEntry);
                    attr = File.GetAttributes(entry);
                    isDirectory = (attr & FileAttributes.Directory) == FileAttributes.Directory;
                    if(!isDirectory)
                        validFiles.Add(subEntry);
                }
            }

        } catch (Exception ex)
        {
            Console.Error.WriteLine(ex); // ignore, proceed
        }

        foreach (FileEntryInfo entry in validFiles)
        {
            string fileName = Path.GetFileName(entry.Path);
            if (fileName.Equals(fileNameToFind, comparison))
                yield return entry;
        }
    }
}

这是我的测试方法:

var allEntriesFound = EnumerateFindFiles("PresentationFramework.dll").ToList();
if(allEntriesFound.Any())
{
    foreach (FileEntryInfo entry in allEntriesFound)
        Console.WriteLine("{0}: Number: {1}", entry.Path, entry.Number);
    // here your exact requirement:
    string result = string.Join(".", allEntriesFound[0].GetNumberTree());
    Console.WriteLine(result);
}

还添加了一种指定根目录的方法,以防止搜索整个文件系统,用法:

var allEntriesFound = EnumerateFindFiles(
  "PresentationFramework.dll", 
  StringComparison.CurrentCultureIgnoreCase,
  new DirectoryInfo(@"C:\Windows"))
.ToList();

【讨论】:

  • 谢谢蒂姆,但我不想找到特定文件,只需为文件夹层次结构分配一个编号,然后将其写入文件。一旦解决了目录编号计算,我还将把它扩展到文件。
猜你喜欢
  • 1970-01-01
  • 2010-12-14
  • 1970-01-01
  • 1970-01-01
  • 2018-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
相关资源
最近更新 更多