【问题标题】:Read subfolder files by giving inner subfolder files priority? [duplicate]通过给予内部子文件夹文件优先级来读取子文件夹文件? [复制]
【发布时间】:2020-12-20 21:26:40
【问题描述】:

我有一个代码,它通过优先考虑每个子文件夹的 dev 文件夹文件,从所有子文件夹(文件夹 1、文件夹 2、...)中读取文件,如下所示:

Products
├── folder1
│   ├── dev
│   │   └── files1.json
│   ├── files1.json
│   ├── files2.json
│   ├── files3.txt
│   ├── prod
│   │   └── files1.json
│   └── stage
│       └── files1.json
├── folder2
│   ├── dev
│   │   └── files5.json
│   ├── files4.json
│   ├── files5.json
│   ├── files6.txt
│   ├── prod
│   │   └── files5.json
│   └── stage
│       └── files5.json
└── folder3
    ├── files10.json
    ├── files7.json
    ├── files8.json
    └── files9.txt

下面是我完成这项工作的代码,但我想如果有的话,我们可以使用linq 以更简单的方式执行以下相同的逻辑吗?意思是在每个子文件夹中优先考虑dev文件夹,然后从子文件夹级别读取所有文件。

private IList<string> ReadFiles(string path)
{
    var allFiles = new List<string>();
    var subFolders = Directory.EnumerateDirectories(path).ToList();
    var fileType = new List<string>() { "*.json", "*.txt" };
    for (int i = 0; i < fileType.Count; i++)
    {
        foreach (var sub in subFolders)
        {
            var jsonFiles = Directory.GetFiles(sub, fileType[i], SearchOption.AllDirectories).ToList();
            var subSubFolders = Directory.EnumerateDirectories(sub).Where(x => x.Contains("dev")).ToList();
            if (subSubFolders.Count > 0)
            {
                var subDev = jsonFiles.Where(x => x.Contains("dev")).ToList();
                jsonFiles.RemoveAll(x => x.Contains("dev"));
                foreach (var item in jsonFiles)
                {
                    var dd = subDev.Where(x => System.IO.File.ReadLines(x).SequenceEqual(System.IO.File.ReadLines(item))).FirstOrDefault();
                    allFiles.Add(dd == null ? item : dd);
                }
            }
            else
            {
                foreach (var item in jsonFiles)
                {
                    allFiles.Add(item);
                }
            }
        }
    }
    return allFiles;
}

【问题讨论】:

  • 您可以枚举所有子文件夹中的所有*.json*.txt文件,然后检查完​​整路径,是否包含dev子文件夹。或按文件名分组(如果它对于整个 Products 文件夹是唯一的)
  • @PavelAnikhouski 您能否举例说明这将如何工作?我只是对如何检查完整路径并有效地完成所有这些感到困惑。文件名不是唯一的。

标签: c# linq file asp.net-core recursion


【解决方案1】:

如何列出文件夹层次结构中的所有 json/txt 文件,并首先处理名为 dev 的文件夹中的文件:

var sc = StringComparison.InvariantCultureIgnoreCase; //because it makes things less wordy later

var files = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories); //all files in all folders

var interestingFiles = files.Where(f => ".json .txt".Contains(Path.GetExtension(f), sc)); //only json/txt files

var devFilesFirst = interestingFiles.OrderByDescending(f => Path.GetFileName(Path.GetDirectoryName(f)).Equals("dev", sc)); //dev files first. bool sorts false(0) then true(1) so we orderby desc

foreach(var file in devFilesFirst )
  ...

您的代码为每个过滤器扩展运行一次目录搜索,这有点低效,而且您枚举起始路径的目录,然后枚举所有返回目录中的文件也有点奇怪;你可以只列举起始路径,不是吗?

所以在上面的代码中,我们枚举了所有目录中的所有文件,并拒绝了那些不是 json 或 txt 的文件,然后我们根据它是否是 dev 命名文件夹中的文件进行排序。这使用 GetDirectoryName 后跟 GetFileName 来提取目录名称。您也可以使用Path.GetDirectoryName(f).EndsWith(Path.DirectorySeparatorChar + "dev", sc),但恕我直言有点冗长


关于“如果我们已经处理过 dev/file1.json,就不要处理 stage/file1.json”:

我们跟踪我们已经看到的开发文件:

var alreadySeen = new HashSet<string>();

foreach(var f in devFilesFirst){
  var fnameLower = Path.GetFileName(f).ToLower();

  if(alreadySeen.Contains(fnameLower))
    continue; //skip it

  ProcessFile(f);

  alreadySeen.Add(fnameLower);
}

对 Add 的调用可能需要“如果父文件夹名称为 dev”检查。如果非开发文件夹中存在多个同名文件,我不太明白该怎么做

我们也可以使用 LINQ GroupBy 执行此操作,并按文件名分组。 GroupBy 可以将文件名列表分解为更短的唯一文件名列表,每个文件名都有一个关联的所有完整文件路径及其名称的列表。您要么只处理相关列表中的第一个文件,要么处理列表中的所有文件,除非第一个文件位于 dev 文件夹中

var groupedByFilename = devFilesFirst.GroupBy(f => Path.GetFileName(f).ToLower());

foreach(var gf in groupedByFilename)
  ProcessFile(gf.First());

【讨论】:

  • 感谢您的建议。我试过你的代码,我想我现在明白它是如何工作的了。我相信你误解了一件事,或者我没有解释清楚。对于那个很抱歉。例如,如果我在folder1 级别中有files1.jsonfiles2.jsonfiles3.json(或.txt 文件),假设files1.json 具有不同的内容也存在于devfolder1 文件夹中,然后在我的最终列表应该只有来自devfolder1 文件夹中的files1.json 文件。在您的示例中,我看到您既有来自dev 文件夹的files1.json,也有folder1 级别。
  • 我已经在最后更新了我的问题,如果你明白的话,我会添加更多细节。
  • 我不太清楚你是否永远不会处理任何与以前处理过的文件同名的文件,或者你是否永远不会处理任何与以前处理过的文件同名的文件在开发文件夹中看到?
  • 想法是如果dev中的文件与subFolder下的文件同名,无论内容是否相同,都应该选择dev中的文件并显示在最终列表中。因此,如果 dev 中的文件是新文件并且它不存在于 subFolder 级别,则应将其添加到最终列表中,但如果 dev 中的文件与子文件夹级别相同,那么我将从子文件夹级别忽略该文件,但将 dev 文件添加到最终名单。
  • 另外我不想在我的最终列表中添加 stage 和 prod 文件,因为我只关心 dev 文件夹文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-03
  • 2020-05-06
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
  • 2023-01-11
相关资源
最近更新 更多