我想我以前知道怎么做,但似乎我已经忘记了。
我有一个递归算法来删除目录树中的所有空目录:
static bool DeleteDirectoriesRecursive(string path)
{
var remove = true;
foreach (var dir in System.IO.Directory.GetDirectories(path))
{
remove &= DeleteDirectoriesRecursive(dir);
}
if (remove &= (System.IO.Directory.GetFiles(path).Length == 0))
System.IO.Directory.Delete(path);
return remove;
}
我正在尝试消除此算法的递归,而不是“修复”算法(即the similar question不使用remove
变量,但我想保留它)。
我已经使用Stack<>
类启动了一个新函数,但我想不出一个返回基本路径并采取子目录已确定的操作的好方法。我想解开非尾递归需要更多的努力。
答案 0 :(得分:1)
sans-recursion版本要困难得多,效率也不高,所以我建议保留你的递归。此外,这是一个更清洁的版本:
static bool DeleteDirectoriesRecursive(DirectoryInfo d)
{
bool remove = true;
foreach (DirectoryInfo c in d.GetDirectories())
{
remove &= DeleteDirectoriesRecursive(c);
}
if (remove && d.GetFiles().Length == 0) {
d.Delete();
return true;
}
return false;
}
答案 1 :(得分:1)
由于Gabe在使用递归时提到了StackOverflowException的可能性,所以我受到了启发,没有它就可以完成这项工作。我使用代码here作为起点。这就是我想出的......
public static bool DeleteDirectories(string root)
{
bool removed = false;
var dirs = new Stack<string>();
var emptyDirStack = new Stack<string>();
var emptyDirs = new Dictionary<string, int>();
if (!System.IO.Directory.Exists(root))
{
throw new ArgumentException();
}
dirs.Push(root);
while (dirs.Count > 0)
{
string currentDir = dirs.Pop();
string[] subDirs;
try
{
subDirs = System.IO.Directory.GetDirectories(currentDir);
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
continue;
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
continue;
}
if (Directory.GetFiles(currentDir).Length == 0)
{
emptyDirStack.Push(currentDir);
emptyDirs.Add(currentDir, subDirs.Length); // add directory path and number of sub directories
}
// Push the subdirectories onto the stack for traversal.
foreach (string str in subDirs)
dirs.Push(str);
}
while (emptyDirStack.Count > 0)
{
string currentDir = emptyDirStack.Pop();
if (emptyDirs[currentDir] == 0)
{
string parentDir = Directory.GetParent(currentDir).FullName;
Console.WriteLine(currentDir); // comment this line
//Directory.Delete(currentDir); // uncomment this line to delete
if (emptyDirs.ContainsKey(parentDir))
{
emptyDirs[parentDir]--; // decrement number of subdirectories of parent
}
removed = true;
}
}
return removed;
}
一些注意事项:
emptyDirs
字典中不包含任何文件的每个目录,以及它包含的子目录数。emptyDirs
字典(我使用Linq来完成此操作)。我想有更有效的方法,但这并不算太糟糕,而且它似乎在我的测试中起作用。
更新: 我摆脱了颠倒的字典而支持第二个堆栈。不过,我仍然使用字典进行快速查找。