简单,不过不是很直接。虽然.NET Framework中提供列举全部子文件的方法,如下:
string[] files = Directory.GetFiles(@"C:\", "*", SearchOption.AllDirectories);
问题是一旦有一个文件夹发生错误,结果异常抛出,然后什么也不会返回。
我写了一个类:FolderExplorer,使用它的ListFiles方法会返回指定文件夹内返回所有可以返回文件,无法访问的子文件夹会跳过。使用Error事件可以查看发生的错误。
举个非常简单的例子:
var folderExplorer = new FolderExplorer();
folderExplorer.Error += (sender, e) =>
{
Console.WriteLine("错误 - 文件夹:{0}, 消息:{1}", e.FolderPath, e.ErrorMessage);
};
//枚举子文件
foreach (var file in folderExplorer.ListFiles(@"C:\a"))
Console.WriteLine(file);
输出示例:
错误 - 文件夹:C:\a\x\b, 消息:Access to the path 'C:\a\x\b\' is denied.
错误 - 文件夹:C:\a\y, 消息:Access to the path 'C:\a\y\' is denied.
C:\a\a.txt
C:\a\x\a.bmp
C:\a\x\a.zip
C:\a\x\a\a.xls
该类型有.NET Framework 4.0+实现,用到了Directory.EnumerateFiles(返回IEnumerable<string>而不是GetFiles方法的string[])和LINQ。
也有.NET Framework 2.0+实现,在2.0下用一个全局的List<string>来保存子文件。
读者可以下载或者在下面浏览源代码。
源代码下载
下载地址
注意:此为微软SkyDrive存档,请用浏览器直接下载,用某些下载工具可能无法下载
文件类型:.cs文件
.NET Framework 4.0实现代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Mgen
{
//文件枚举 .NET 4.0 +
//Updates: http://www.cnblogs.com/mgen/archive/2012/04/10/2440570.html
public class FolderExplorer
{
#region 错误事件
public event EventHandler<FolderErrorEventArgs> Error;
protected virtual void OnError(FolderErrorEventArgs e)
{
var handler = this.Error;
if (handler != null)
handler(this, e);
}
#endregion
/// <summary>
/// 枚举文件夹内的所有文件
/// </summary>
/// <param name="folder"></param>
/// <returns></returns>
public IEnumerable<string> ListFiles(string folder)
{
if (folder == null)
throw new ArgumentNullException("folder");
return InternalListFiles(folder);
}
#region 私有方法
IEnumerable<string> InternalListFiles(string folder)
{
try
{
var files = Directory.EnumerateFiles(folder);
foreach (var dir in Directory.EnumerateDirectories(folder))
files = files.Concat(InternalListFiles(dir));
return files;
}
catch (Exception ex)
{
OnError(new FolderErrorEventArgs(folder, ex.Message));
return Enumerable.Empty<string>();
}
}
#endregion
}
// 错误事件参数
public class FolderErrorEventArgs : EventArgs
{
public string FolderPath { get; private set; }
public string ErrorMessage { get; private set; }
public FolderErrorEventArgs(string folder, string err)
{
FolderPath = folder;
ErrorMessage = err;
}
}
}
.NET Framework 2.0+实现代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Mgen
{
//文件枚举 .NET 2.0 +
//Updates: http://www.cnblogs.com/mgen/archive/2012/04/10/2440570.html
public class FolderExplorer
{
#region 错误事件
public event EventHandler<FolderErrorEventArgs> Error;
protected virtual void OnError(FolderErrorEventArgs e)
{
var handler = this.Error;
if (handler != null)
handler(this, e);
}
#endregion
/// <summary>
/// 枚举文件夹内的所有文件
/// </summary>
/// <param name="folder"></param>
/// <returns></returns>
public string[] ListFiles(string folder)
{
if (folder == null)
throw new ArgumentNullException("folder");
var result = new List<string>();
InternalListFiles(folder, result);
return result.ToArray();
}
#region 私有方法
void InternalListFiles(string folder, List<string> result)
{
try
{
result.AddRange(Directory.GetFiles(folder));
foreach (var dir in Directory.GetDirectories(folder))
InternalListFiles(dir, result);
}
catch (Exception ex)
{
OnError(new FolderErrorEventArgs(folder, ex.Message));
}
}
#endregion
}
// 错误事件参数
public class FolderErrorEventArgs : EventArgs
{
public string FolderPath { get; private set; }
public string ErrorMessage { get; private set; }
public FolderErrorEventArgs(string folder, string err)
{
FolderPath = folder;
ErrorMessage = err;
}
}
}