遍历文件系统目录树的深入理解
在c#中可以遍历指定驱动器或指定目录下嵌套目录中的所有文件或者任意深度的文件。通过遍历可以检索string形式的目录名和文件名,也可以检索 System.IO.FileInfo 或 System.IO.DirectoryInfo 对象形式的其他信息。可以通过递归遍历和堆栈遍历两种方式实现目录遍历。
递归遍历
递归算法简单,但嵌套树太深,可能会引起堆栈溢出异常。
代码如下:
/// <summary>
/// 通过递归方式访问目录树
/// </summary>
class RecursiveAccessDirectory
{
//声明并实例化一个字符串集合
static System.Collections.Specialized.StringCollection log
= new System.Collections.Specialized.StringCollection();
static void Main()
{
/*该部门代码循环访问本机所有驱动器上的文件
*
*
//返回计算机逻辑驱动器名称的字符串数组
//包括光驱及连接计算机的移动驱动器
string[] drives = System.Environment.GetLogicalDrives();
foreach (string dr in drives)
{
System.IO.DriveInfo di = new System.IO.DriveInfo(dr);
if (!di.IsReady)
{
Console.WriteLine("驱动器 {0} 不能读出", di.Name);
continue;
}
System.IO.DirectoryInfo rootDir = di.RootDirectory;
WalkDirectoryTree(rootDir);
}
*/
/*循环访问指定目录下的文件夹
*
*/
System.IO.DirectoryInfo rootDir = new System.IO.DirectoryInfo(@"C:\test");
WalkDirectoryTree(rootDir);
Console.WriteLine("限制用户访问文件:");
foreach (string s in log)
{
Console.WriteLine(s);
}
Console.Read();
}
static void WalkDirectoryTree(System.IO.DirectoryInfo root)
{
System.IO.FileInfo[] files = null;
System.IO.DirectoryInfo[] subDirs = null;
try
{
//GetFiles方法的参数可以包含通配符。
//即使目录下没有匹配的文件,返回长度为0不为空的数组对象,
//所以递归函数可以放在if (files != null)里。
//下面为查找所有有后缀名的文件。
files = root.GetFiles("*.*");
}
//请求权限超过应用程序提供权限抛出异常
catch (System.UnauthorizedAccessException e)
{
//在访问某个文件夹遭受拒绝时,
//您可以提升自己的权限,然后再次访问它。
log.Add(e.Message);
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
}
if (files != null)
{
foreach (System.IO.FileInfo fi in files)
{
Console.WriteLine("{0}: {1} {2}", fi.FullName, fi.Length, fi.CreationTime);
}
subDirs = root.GetDirectories();
foreach (System.IO.DirectoryInfo dirInfo in subDirs)
{
WalkDirectoryTree(dirInfo);
}
}
}
}
堆栈遍历
利用泛型 Stack<T> 集合类型实现,该类型是一个后进先出 (LIFO) 堆栈。
代码如下:
/// <summary>
/// 通过堆栈方式访问目录树
/// </summary>
class StackAccessDirectory
{
static void Main()
{
TraverseTree(@"C:\test");
Console.Read();
}
public static void TraverseTree(string root)
{
Stack<string> dirs = new Stack<string>(20);
if (!System.IO.Directory.Exists(root))
{
throw new ArgumentException();
}
dirs.Push(root);
while (dirs.Count > 0)
{
string currDir = dirs.Pop();
string[] subDirs;
try
{
subDirs = System.IO.Directory.GetDirectories(currDir);
}
catch (System.UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
continue;
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
continue;
}
string[] files=null;
try
{
files=System.IO.Directory.GetFiles(currDir);
}
catch(System.UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
continue;
}
catch(System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
continue;
}
foreach (string file in files)
{
try
{
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)
{
Console.WriteLine(e.Message);
continue;
}
}
foreach (string str in subDirs)
dirs.Push(str);
}
}
}