In primo luogo, perdona il mio povero inglese; o) ho avuto un problema che mi ha portato a questa pagina: enumerare i file di una directory e le sue sottodirectory senza bloccare su un UnauthorizedAccessException, e, come il nuovo metodo di .Net 4 DirectoryInfo .Enumerare ..., ottenere il primo risultato prima della fine dell'intera query.
Con l'aiuto di vari esempi trovati qua e là sul web, ho finalmente scrivere questo metodo:
public static IEnumerable<FileInfo> EnumerateFiles_Recursive(this DirectoryInfo directory, string searchPattern, SearchOption searchOption, Func<DirectoryInfo, Exception, bool> handleExceptionAccess)
{
Queue<DirectoryInfo> subDirectories = new Queue<DirectoryInfo>();
IEnumerable<FileSystemInfo> entries = null;
// Try to get an enumerator on fileSystemInfos of directory
try
{
entries = directory.EnumerateFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly);
}
catch (Exception e)
{
// If there's a callback delegate and this delegate return true, we don't throw the exception
if (handleExceptionAccess == null || !handleExceptionAccess(directory, e))
throw;
// If the exception wasn't throw, we make entries reference an empty collection
entries = EmptyFileSystemInfos;
}
// Yield return file entries of the directory and enqueue the subdirectories
foreach (FileSystemInfo entrie in entries)
{
if (entrie is FileInfo)
yield return (FileInfo)entrie;
else if (entrie is DirectoryInfo)
subDirectories.Enqueue((DirectoryInfo)entrie);
}
// If recursive search, we make recursive call on the method to yield return entries of the subdirectories.
if (searchOption == SearchOption.AllDirectories)
{
DirectoryInfo subDir = null;
while (subDirectories.Count > 0)
{
subDir = subDirectories.Dequeue();
foreach (FileInfo file in subDir.EnumerateFiles_Recursive(searchPattern, searchOption, handleExceptionAccess))
{
yield return file;
}
}
}
else
subDirectories.Clear();
}
Io uso una coda e un metodo ricorsivo per mantenere l'ordine tradizionale (contenuto della directory e quindi il contenuto della prima sottodirectory e le sue sottodirectory e poi il contenuto del secondo ...). Il parametro "handleExceptionAccess" è solo una chiamata di funzione quando viene generata un'eccezione con una directory; la funzione deve restituire true per indicare che l'eccezione deve essere ignorata.
Con questo methode, è possibile scrivere:
DirectoryInfo dir = new DirectoryInfo("c:\\temp");
long size = dir.EnumerateFiles_Recursive("*", SearchOption.AllDirectories, (d, ex) => true).Sum(f => f.Length);
Ed eccoci qui: tutti un'eccezione durante il tentativo di enumerare una directory sarà ignorare!
Spero che questo aiuto
Lionel
PS: per un motivo che non so spiegare, il mio metodo è più veloce rispetto al quadro 4 one ...
PPS: si può ottenere la mia provare le soluzioni con la fonte per questi metodi: qui TestDirEnumerate. Scrivo EnumerateFiles_Recursive, EnumerateFiles_NonRecursive (usa una coda per evitare la ricorsione) e EnumerateFiles_NonRecursive_TraditionalOrder (usa una pila di code per evitare la ricorsione e mantenere l'ordine tradizionale). Mantenere quei 3 metodi non ha alcun interesse, li scrivo solo per testare il migliore. Penso di mantenere solo l'ultimo. Ho anche scritto l'equivalente per EnumerateFileSystemInfos e EnumerateDirectories.
Grazie per questo :) – ThePower