在 C:
,我有 * foobar的
文件数万。他们在各种各样的地方(即子目录)。这些文件是大致1 - 64 kb的大小,和明文
我有一个 Foobar的类(字符串fileContents)
是强烈的类型,这些 .foobar
文件。
我的挑战是获得所有C的
,再$ P。 $ psented为 * foobar的
文件的列表: Foobar的
对象的数组。什么是做到这一点的最快方法是什么?
我很感兴趣,以找出是否有更好的办法(毫无疑问)比我的第一种方法,它遵循的,如果我的这个做法有什么潜在的问题(例如I / O并发问题抛出异常?):
var中的文件= Directory.EnumerateFiles
(ROOTPATH,* .foobar,SearchOption.AllDirectories);
Foobar的[] foobars =
(
从文件路径中files.AsParallel()
让内容= File.ReadAllText(文件路径)
选择新的Foobar的(内容)
)
.ToArray();
解决方案
由于权限错误(或其他错误)能明显停止枚举死在其轨道上,你可能想实现自己的枚举是这样的:
类SafeFileEnumerator:IEnumerable的<字符串>
{
私人串根;
私人字符串的模式;
私人的IList<异常>错误;
公共SafeFileEnumerator(串根,字符串模式)
{
this.root =根;
this.pattern =格局;
this.errors =新的名单,其中,异常>();
}
公共SafeFileEnumerator(串根,细绳纹,IList的<异常>错误)
{
this.root =根;
this.pattern =格局;
this.errors =错误;
}
公共异常[]错误()
{
返回errors.ToArray();
}
类枚举:IEnumerator的<字符串>
{
IEnumerator的<字符串> fileEnumerator;
IEnumerator的<字符串> directoryEnumerator;
串根;
字符串模式;
IList的<异常>错误;
公共枚举(串根,细绳纹,IList的<异常>错误)
{
this.root =根;
this.pattern =格局;
this.errors =错误;
fileEnumerator = System.IO.Directory.EnumerateFiles(根,花纹).GetEnumerator();
directoryEnumerator = System.IO.Directory.EnumerateDirectories(根).GetEnumerator();
}
公共串电流
{
得到
{
如果(fileEnumerator == NULL)抛出新的ObjectDisposedException(FileEnumerator);
返回fileEnumerator.Current;
}
}
公共无效的Dispose()
{
如果(fileEnumerator!= NULL)
fileEnumerator.Dispose();
fileEnumerator = NULL;
如果(directoryEnumerator!= NULL)
directoryEnumerator.Dispose();
directoryEnumerator = NULL;
}
对象System.Collections.IEnumerator.Current
{
{返回电流; }
}
公共BOOL的MoveNext()
{
如果((fileEnumerator = NULL)及!及(fileEnumerator.MoveNext()))
返回true;
而((directoryEnumerator = NULL)及!及(directoryEnumerator.MoveNext()))
{
如果(fileEnumerator!= NULL)
fileEnumerator.Dispose();
尝试
{
fileEnumerator =新SafeFileEnumerator(directoryEnumerator.Current,图案,错误).GetEnumerator();
}
赶上(例外前)
{
errors.Add(前);
继续;
}
如果(fileEnumerator.MoveNext())
返回true;
}
如果(fileEnumerator!= NULL)
fileEnumerator.Dispose();
fileEnumerator = NULL;
如果(directoryEnumerator!= NULL)
directoryEnumerator.Dispose();
directoryEnumerator = NULL;
返回false;
}
公共无效复位()
{
的Dispose();
fileEnumerator = System.IO.Directory.EnumerateFiles(根,花纹).GetEnumerator();
directoryEnumerator = System.IO.Directory.EnumerateDirectories(根).GetEnumerator();
}
}
公众的IEnumerator<字符串>的GetEnumerator()
{
返回新的枚举(根,模式,错误);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
返回的GetEnumerator();
}
}
On c:
, I have tens of thousands of *.foobar
files. They're in all sorts of places (i.e. subdirs). These files are roughly 1 - 64 kb in size, and plaintext.
I have a class Foobar(string fileContents)
that strongly types these .foobar
files.
My challenge to is get a list of all the *.foobar
files on c:
, represented as an array of Foobar
objects. What's the quickest way to do this?
I'm interested to find out if there's a better way (undoubtedly) than my first approach, which follows, and if this approach of mine has any potential problems (e.g. I/O concurrency issues throwing exceptions?):
var files = Directory.EnumerateFiles
(rootPath, "*.foobar", SearchOption.AllDirectories);
Foobar[] foobars =
(
from filePath in files.AsParallel()
let contents = File.ReadAllText(filePath)
select new Foobar(contents)
)
.ToArray();
解决方案
Because permission errors (or other errors) can apparently stop the enumeration dead in its tracks, you may want to implement your own enumerator something like this:
class SafeFileEnumerator : IEnumerable<string>
{
private string root;
private string pattern;
private IList<Exception> errors;
public SafeFileEnumerator(string root, string pattern)
{
this.root = root;
this.pattern = pattern;
this.errors = new List<Exception>();
}
public SafeFileEnumerator(string root, string pattern, IList<Exception> errors)
{
this.root = root;
this.pattern = pattern;
this.errors = errors;
}
public Exception[] Errors()
{
return errors.ToArray();
}
class Enumerator : IEnumerator<string>
{
IEnumerator<string> fileEnumerator;
IEnumerator<string> directoryEnumerator;
string root;
string pattern;
IList<Exception> errors;
public Enumerator(string root, string pattern, IList<Exception> errors)
{
this.root = root;
this.pattern = pattern;
this.errors = errors;
fileEnumerator = System.IO.Directory.EnumerateFiles(root, pattern).GetEnumerator();
directoryEnumerator = System.IO.Directory.EnumerateDirectories(root).GetEnumerator();
}
public string Current
{
get
{
if (fileEnumerator == null) throw new ObjectDisposedException("FileEnumerator");
return fileEnumerator.Current;
}
}
public void Dispose()
{
if (fileEnumerator != null)
fileEnumerator.Dispose();
fileEnumerator = null;
if (directoryEnumerator != null)
directoryEnumerator.Dispose();
directoryEnumerator = null;
}
object System.Collections.IEnumerator.Current
{
get { return Current; }
}
public bool MoveNext()
{
if ((fileEnumerator != null) && (fileEnumerator.MoveNext()))
return true;
while ((directoryEnumerator != null) && (directoryEnumerator.MoveNext()))
{
if (fileEnumerator != null)
fileEnumerator.Dispose();
try
{
fileEnumerator = new SafeFileEnumerator(directoryEnumerator.Current, pattern, errors).GetEnumerator();
}
catch (Exception ex)
{
errors.Add(ex);
continue;
}
if (fileEnumerator.MoveNext())
return true;
}
if (fileEnumerator != null)
fileEnumerator.Dispose();
fileEnumerator = null;
if (directoryEnumerator != null)
directoryEnumerator.Dispose();
directoryEnumerator = null;
return false;
}
public void Reset()
{
Dispose();
fileEnumerator = System.IO.Directory.EnumerateFiles(root, pattern).GetEnumerator();
directoryEnumerator = System.IO.Directory.EnumerateDirectories(root).GetEnumerator();
}
}
public IEnumerator<string> GetEnumerator()
{
return new Enumerator(root, pattern, errors);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}