C# 递归搜索目录中的文件
我有下面的代码通过一个目录递归搜索文件,该目录将所有xml文件的列表返回给我。除了根目录中的xml文件不包括在列表中之外,所有这些都可以正常工作 我理解为什么,因为它做的第一件事是获取根目录中的目录,然后获取文件,因此错过了对根目录的GetFiles()调用。我尝试在foreach之前包含GetFiles()调用,但结果并不像我预期的那样C# 递归搜索目录中的文件,c#,recursion,C#,Recursion,我有下面的代码通过一个目录递归搜索文件,该目录将所有xml文件的列表返回给我。除了根目录中的xml文件不包括在列表中之外,所有这些都可以正常工作 我理解为什么,因为它做的第一件事是获取根目录中的目录,然后获取文件,因此错过了对根目录的GetFiles()调用。我尝试在foreach之前包含GetFiles()调用,但结果并不像我预期的那样 public static ArrayList DirSearch(string sDir) { try { foreach
public static ArrayList DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d, "*.xml"))
{
string extension = Path.GetExtension(f);
if (extension != null && (extension.Equals(".xml")))
{
fileList.Add(f);
}
}
DirSearch(d);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return fileList;
}
我的目录结构类似于:
RootDirectory
test1.0.xml
test1.1.xml
test1.2.xml
2ndLevDir
test2.0.xml
test2.1.xml
3rdLevDir
test3.0.xml
test3.1.xml
var extensions = new List<string> { ".txt", ".xml" };
string[] files = Directory.GetFiles(sDir, "*.*", SearchOption.AllDirectories)
.Where(f => extensions.IndexOf(Path.GetExtension(f)) >= 0).ToArray();
代码返回:
test2.0.xml
test2.1.xml
test3.0.xml
test3.1.xml
我想返回每个文件,包括:
test1.0.xml
test1.1.xml
test1.2.xml
不太好用递归。任何指针都将不胜感激。您应该在目录上的循环之前或之后对文件进行循环,但不要像您所做的那样嵌套在其中
foreach (string f in Directory.GetFiles(d, "*.xml"))
{
string extension = Path.GetExtension(f);
if (extension != null && (extension.Equals(".xml")))
{
fileList.Add(f);
}
}
foreach (string d in Directory.GetDirectories(sDir))
{
DirSearch(d);
}
您可以使用搜索子目录,例如:
string[] files = Directory.GetFiles(sDir, "*.xml", SearchOption.AllDirectories);
这样只能搜索一个扩展,但您可以使用以下内容:
RootDirectory
test1.0.xml
test1.1.xml
test1.2.xml
2ndLevDir
test2.0.xml
test2.1.xml
3rdLevDir
test3.0.xml
test3.1.xml
var extensions = new List<string> { ".txt", ".xml" };
string[] files = Directory.GetFiles(sDir, "*.*", SearchOption.AllDirectories)
.Where(f => extensions.IndexOf(Path.GetExtension(f)) >= 0).ToArray();
请参阅文档以了解可能引发的异常,例如,如果代码在没有适当访问权限的帐户下运行,则UnauthorizedAccessException。请尝试以下方法:
public static IEnumerable<string> GetXMLFiles(string directory)
{
List<string> files = new List<string>();
try
{
files.AddRange(Directory.GetFiles(directory, "*.xml", SearchOption.AllDirectories));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return files;
}
公共静态IEnumerable GetXMLFiles(字符串目录)
{
列表文件=新列表();
尝试
{
files.AddRange(Directory.GetFiles(Directory,*.xml),SearchOption.AllDirectories));
}
捕获(例外情况除外)
{
控制台写入线(例如消息);
}
归还文件;
}
这将递归返回所有xml文件:
var allFiles = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories);
public static List<string> DirSearch(string sDir, List<string> files)
{
foreach (string f in Directory.GetFiles(sDir, "*.xml"))
{
string extension = Path.GetExtension(f);
if (extension != null && (extension.Equals(".xml")))
{
files.Add(f);
}
}
foreach (string d in Directory.GetDirectories(sDir))
{
DirSearch(d, files);
}
return files;
}
公共静态列表目录搜索(字符串sDir,列表文件)
{
foreach(Directory.GetFiles(sDir,*.xml)中的字符串f)
{
字符串扩展名=Path.GetExtension(f);
if(extension!=null&(extension.Equals(.xml)))
{
添加(f);
}
}
foreach(Directory.GetDirectories(sDir)中的字符串d)
{
DirSearch(d,文件);
}
归还文件;
}
那就这样说吧
List<string> files = DirSearch("c:\foo", new List<string>());
List files=DirSearch(“c:\foo”,new List());
更新:
我不知道,直到我读到另一个答案,已经有一个内置的机制来实现这一点。如果您有兴趣了解如何修改代码以使其正常工作,我将留下我的答案。您正在创建三个列表,而不是使用一个列表(您不使用
DirSearch(d)
的返回值)。可以使用列表作为参数来保存状态:
static void Main(string[] args)
{
var list = new List<string>();
DirSearch(list, ".");
foreach (var file in list)
{
Console.WriteLine(file);
}
}
public static void DirSearch(List<string> files, string startDirectory)
{
try
{
foreach (string file in Directory.GetFiles(startDirectory, "*.*"))
{
string extension = Path.GetExtension(file);
if (extension != null)
{
files.Add(file);
}
}
foreach (string directory in Directory.GetDirectories(startDirectory))
{
DirSearch(files, directory);
}
}
catch (System.Exception e)
{
Console.WriteLine(e.Message);
}
}
static void Main(字符串[]args)
{
var list=新列表();
目录搜索(列表“.”);
foreach(列表中的var文件)
{
Console.WriteLine(文件);
}
}
公共静态void目录搜索(列表文件、字符串开始目录)
{
尝试
{
foreach(Directory.GetFiles(startDirectory,*.*)中的字符串文件)
{
字符串扩展名=Path.GetExtension(文件);
if(扩展名!=null)
{
文件。添加(文件);
}
}
foreach(directory.getdirectory(startDirectory)中的字符串目录)
{
目录搜索(文件、目录);
}
}
捕获(System.e例外)
{
控制台写入线(e.Message);
}
}
您可以执行以下操作:
foreach (var file in Directory.GetFiles(MyFolder, "*.xml", SearchOption.AllDirectories))
{
// do something with this file
}
使用EnumerateFiles获取嵌套目录中的文件。 使用AllDirectory在所有目录中递归
using System;
using System.IO;
class Program
{
static void Main()
{
// Call EnumerateFiles in a foreach-loop.
foreach (string file in Directory.EnumerateFiles(@"c:\files",
"*.xml",
SearchOption.AllDirectories))
{
// Display file path.
Console.WriteLine(file);
}
}
}
对于文件和目录搜索的目的,我想提供使用专门的多线程.NET库,它拥有广泛的搜索机会,工作速度非常快 您可以在GitHub上找到有关库的所有信息: 如果您想下载,可以在以下位置下载: 如果你有任何问题,请问他们 这是一个演示示例,说明了如何使用它:
class Searcher
{
private static object locker = new object();
private FileSearcher searcher;
List<FileInfo> files;
public Searcher()
{
files = new List<FileInfo>(); // create list that will contain search result
}
public void Startsearch()
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
// create tokenSource to get stop search process possibility
searcher = new FileSearcher(@"C:\", (f) =>
{
return Regex.IsMatch(f.Name, @".*[Dd]ragon.*.jpg$");
}, tokenSource); // give tokenSource in constructor
searcher.FilesFound += (sender, arg) => // subscribe on FilesFound event
{
lock (locker) // using a lock is obligatorily
{
arg.Files.ForEach((f) =>
{
files.Add(f); // add the next received file to the search results list
Console.WriteLine($"File location: {f.FullName}, \nCreation.Time: {f.CreationTime}");
});
if (files.Count >= 10) // one can choose any stopping condition
searcher.StopSearch();
}
};
searcher.SearchCompleted += (sender, arg) => // subscribe on SearchCompleted event
{
if (arg.IsCanceled) // check whether StopSearch() called
Console.WriteLine("Search stopped.");
else
Console.WriteLine("Search completed.");
Console.WriteLine($"Quantity of files: {files.Count}"); // show amount of finding files
};
searcher.StartSearchAsync();
// start search process as an asynchronous operation that doesn't block the called thread
}
}
类搜索器
{
私有静态对象锁定器=新对象();
私有文件搜索器;
列出文件;
公共搜索者()
{
files=new List();//创建将包含搜索结果的列表
}
公共无效Startsearch()
{
CancellationTokenSource tokenSource=新的CancellationTokenSource();
//创建tokenSource以获取停止搜索过程的可能性
searcher=newfilesearcher(@“C:\”,(f)=>
{
返回Regex.IsMatch(f.Name,@“*[Dd]ragon.*.jpg$”;
},tokenSource);//在构造函数中指定tokenSource
searcher.FilesFound+=(发件人,参数)=>//订阅FilesFound事件
{
锁(储物柜)//使用锁是强制性的
{
arg.Files.ForEach((f)=>
{
files.Add(f);//将下一个收到的文件添加到搜索结果列表中
WriteLine($“文件位置:{f.FullName},\n创建时间:{f.CreationTime}”);
});
如果(files.Count>=10)//可以选择任何停止条件
searcher.StopSearch();
}
};
searcher.SearchCompleted+=(发件人,arg)=>//订阅SearchCompleted事件
{
if(arg.IsCanceled)//检查是否调用了StopSearch()
控制台.WriteLine(“搜索已停止”);
其他的
Console.WriteLine(“搜索已完成”);
Console.WriteLine($“文件数量:{files.Count}”);//显示查找文件的数量
};
startsearchsync();
//将搜索进程作为一个异步操作启动,该操作不会阻止被调用的线程
}
}
我尝试了这里列出的一些其他解决方案,但在单元测试期间,代码会抛出我想忽略的异常。我最终创建了以下递归搜索方法,该方法将忽略某些异常,如PathToolOngA异常