У меня есть текстовый файл с путями к папкам, который выглядит так
Folder1
Folder1/SubFolder1
Folder1/SubFolder1/SubSubFolder1
Folder1/SubFolder1/SubSubFolder2
Folder1/SubFolder1/SubSubFolder3
Folder1/SubFolder1/SubSubFolder4
Folder1/SubFolder2
Folder1/SubFolder2/SubSubFolder1
Folder1/SubFolder2/SubSubFolder2
Folder1/SubFolder2/SubSubFolder3
Folder1/SubFolder2/SubSubFolder4
Folder1/SubFolder2/SubSubFolder5
Folder1/SubFolder2/SubSubFolder6
Folder1/SubFolder2/SubSubFolder6/SubSubSubFolder1
Folder1/SubFolder3
Folder2
Folder2/SubFolder1
Folder2/SubFolder1/SubSubFolder1
Folder2/SubFolder1/SubSubFolder2
Folder2/SubFolder1/SubSubFolder3
Folder2/SubFolder1/SubSubFolder4
Folder2/SubFolder2
Folder2/SubFolder2/SubSubFolder1
Folder2/SubFolder2/SubSubFolder2
Folder2/SubFolder2/SubSubFolder3
Folder2/SubFolder2/SubSubFolder4
Folder2/SubFolder2/SubSubFolder5
Folder2/SubFolder2/SubSubFolder6
Folder2/SubFolder2/SubSubFolder7
Folder2/SubFolder2/SubSubFolder6/SubSubSubFolder1
Folder2/SubFolder3
Folder2/SubFolder4
Теперь мне нужен словарь строк и целых чисел, в котором сохраняется имя и количество папок. количество файлов/папок в нем (только верхний уровень)
Folder1, 3 // SubFolder1, SubFolder2, SubFolder3
Folder1/SubFolder1,4 // SubSubFolder1, SubSubFolder2, SubSubFolder3,
Folder1/SubFolder2,6 //SubSubFolder1, SubSubFolder2, SubSubFolder3, SubSubFolder4, SubSubFolder5, SubSubFolder6
Folder1/SubFolder2/SubSubFolder6,1 //SubSubSubFolder1
Folder1/SubFolder3,0
Folder2,4 // SubFolder1, SubFolder2, SubFolder3, SubFolder4
Folder2/SubFolder1,4 // SubSubFolder1, SubSubFolder2, SubSubFolder3, SubSubFolder4
Folder2/SubFolder2,7 // SubSubFolder1, SubSubFolder2, SubSubFolder3, SubSubFolder4, SubSubFolder5, SubSubFolder6, SubSubFolder7
Folder2/SubFolder2/SubSubFolder6,1 //SubSubSubFolder1
Folder2/SubFolder3,0
Folder2/SubFolder4,0
Я могу перебрать все строки, но думаю, это будет немного сложно и запутанно.
var allLines = File.ReadAllLines(filePath);
foreach (var line in allLines)
{
var subFolderCount = 0;
var subFolderPath = Path.Combine(folderPath, line);
//...
}
но мне было интересно, есть ли более простой и эффективный способ сделать это?
Да @TimSchmelter, проверка непосредственно из файла/папки была бы простой. Directory.EnumerateDirectories(path, TopDirectoryOnly), но у меня есть только этот текстовый файл
@Pankay: Почему в этом словаре находится «SubSubFolder4/Folder1/SubFolder2»? Это не строка в файле
@TimSchmelter, исправил, должно быть, ошибка при наборе текста.
Почему Folder2/SubFolder4,0
и т. д. присутствуют, когда, например, Folder2/SubFolder2/SubSubFolder7,0
нет? если не считать того, что это выглядит просто allLines.ToLookup(Path.GetDirectoryName).Select(l => $"{l.Key},{l.Count()}")
Итак, как было сказано, вы просто хотите проанализировать содержимое файла, а не фактические папки в вашей ОС, тогда это должно работать так, как ожидалось:
public static Dictionary<string, int> GetTopLevelFolderCount(IList<string> lines)
{
return lines
.GroupBy(l => l)
.ToDictionary(
g => g.Key,
g => lines.Count(l => l.StartsWith(g.Key, StringComparison.OrdinalIgnoreCase)
&& l[g.Key.Length..].Count(c => c == '/') == 1));
}
Редактировать: вот демо: https://dotnetfiddle.net/iitkb9
Эффективный способ справиться с этим — заполнить дерево данными.
Сначала мы определяем TreeNode
:
public class TreeNode
{
private readonly Dictionary<string, TreeNode> _children = new();
public IReadOnlyDictionary<string, TreeNode> Children => _children;
public void Push(IEnumerable<string> pathParts)
{
var currentNode = this;
foreach (var pathPart in pathParts)
{
currentNode = currentNode.GetOrCreateChildNode(pathPart);
}
}
private TreeNode GetOrCreateChildNode(string pathPart)
{
if (_children.TryGetValue(pathPart, out var childNode))
return childNode;
childNode = new TreeNode();
_children[pathPart] = childNode;
return childNode;
}
}
Затем мы создаем корневой узел и заполняем дерево отсюда:
var rootNode = new TreeNode();
foreach (var line in File.ReadLines(fileName))
{
rootNode.Push(line.Split('/'));
}
Наконец, мы проходим по дереву, чтобы отобразить нужную информацию:
void Print(TreeNode treeNode, string path)
{
foreach (var kvp in treeNode.Children)
{
var subPath = path is "" ? kvp.Key : path + '/' + kvp.Key;
Console.WriteLine($"{subPath}, {kvp.Value.Children.Count}");
Print(kvp.Value, subPath);
}
}
И назовите это так:
Print(rootNode, string.Empty);
Рабочий код доступен здесь.
Итак, вы не хотите использовать методы
File
, чтобы проверить, сколько файлов/папок на самом деле находится в этой папке, а просто проверяете содержимое этого текстового файла?