C# 如何使用多个条件筛选Directory.Enumerate文件?
我有以下代码:C# 如何使用多个条件筛选Directory.Enumerate文件?,c#,.net,C#,.net,我有以下代码: List<string> result = new List<string>(); foreach (string file in Directory.EnumerateFiles(path,"*.*", SearchOption.AllDirectories) .Where(s => s.EndsWith(".mp3") || s.EndsWith(".wma"))) { result
List<string> result = new List<string>();
foreach (string file in Directory.EnumerateFiles(path,"*.*",
SearchOption.AllDirectories)
.Where(s => s.EndsWith(".mp3") || s.EndsWith(".wma")))
{
result.Add(file);
}
使用NETFramework4.0/LINQ最有效的方法是什么?有什么建议吗
作为一名临时程序员,我非常感谢任何帮助:-)从LINQ上下文中剥离,这归结为如何找出文件是否与扩展名列表匹配
System.IO.Path.GetExtension()
在这里比String.EndsWith()
更好。根据集合的不同,多个|
可以替换为.Contains()
或.IndexOf()
var extensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{ ".mp3", ".wma", ".mp4", ".wav" };
... s => extensions.Contains(Path.GetExtension(s))
var extensions=newhashset(StringComparer.OrdinalIgnoreCase)
{.mp3“,.wma“,.mp4“,.wav”};
... s=>extensions.Contains(Path.GetExtension)
string path=“C:\\”;
var result=新列表();
字符串[]扩展名={.mp3“,.wma“,.mp4“,.wav”};
foreach(目录.EnumerateFiles(路径“***”),SearchOption.AllDirectory中的字符串文件)
.Where(s=>extensions.Any(ext=>ext==Path.GetExtension(s)))
{
结果.添加(文件);
Console.WriteLine(文件);
}
我创建了一些帮助器方法来解决这个问题,这是我今年早些时候提到的
一个版本采用regex模式\.mp3\.mp4
,另一个版本采用字符串列表并并行运行
public static class MyDirectory
{ // Regex version
public static IEnumerable<string> GetFiles(string path,
string searchPatternExpression = "",
SearchOption searchOption = SearchOption.TopDirectoryOnly)
{
Regex reSearchPattern = new Regex(searchPatternExpression, RegexOptions.IgnoreCase);
return Directory.EnumerateFiles(path, "*", searchOption)
.Where(file =>
reSearchPattern.IsMatch(Path.GetExtension(file)));
}
// Takes same patterns, and executes in parallel
public static IEnumerable<string> GetFiles(string path,
string[] searchPatterns,
SearchOption searchOption = SearchOption.TopDirectoryOnly)
{
return searchPatterns.AsParallel()
.SelectMany(searchPattern =>
Directory.EnumerateFiles(path, searchPattern, searchOption));
}
}
公共静态类MyDirectory
{//Regex版本
公共静态IEnumerable GetFiles(字符串路径,
字符串searchPatternExpression=“”,
SearchOption SearchOption=SearchOption.TopDirectoryOnly)
{
Regex reSearchPattern=newregex(searchPatternExpression,RegexOptions.IgnoreCase);
返回目录.枚举文件(路径“*”,搜索选项)
.Where(文件=>
reSearchPattern.IsMatch(Path.GetExtension(文件));
}
//采用相同的模式,并并行执行
公共静态IEnumerable GetFiles(字符串路径,
字符串[]搜索模式,
SearchOption SearchOption=SearchOption.TopDirectoryOnly)
{
返回searchPatterns.AsParallel()
.SelectMany(searchPattern=>
枚举文件(路径、搜索模式、搜索选项));
}
}
我知道这是一篇老文章,但我提出了一个人们可能喜欢使用的解决方案
private IEnumerable<FileInfo> FindFiles()
{
DirectoryInfo sourceDirectory = new DirectoryInfo(@"C:\temp\mydirectory");
string foldersFilter = "*bin*,*obj*";
string fileTypesFilter = "*.mp3,*.wma,*.mp4,*.wav";
// filter by folder name and extension
IEnumerable<DirectoryInfo> directories = foldersFilter.Split(',').SelectMany(pattern => sourceDirectory.EnumerateDirectories(pattern, SearchOption.AllDirectories));
List<FileInfo> files = new List<FileInfo>();
files.AddRange(directories.SelectMany(dir => fileTypesFilter.Split(',').SelectMany(pattern => dir.EnumerateFiles(pattern, SearchOption.AllDirectories))));
// Pick up root files
files.AddRange(fileTypesFilter.Split(',').SelectMany(pattern => sourceDirectory.EnumerateFiles(fileTypesFilter, SearchOption.TopDirectoryOnly)));
// filter just by extension
IEnumerable<FileInfo> files2 = fileTypesFilter.Split(',').SelectMany(pattern => sourceDirectory.EnumerateFiles(pattern, SearchOption.AllDirectories));
}
private IEnumerable FindFiles()
{
DirectoryInfo sourceDirectory=newdirectoryinfo(@“C:\temp\mydirectory”);
字符串foldersFilter=“*bin*,*obj*”;
字符串文件类型过滤器=“*.mp3,*.wma,*.mp4,*.wav”;
//按文件夹名称和扩展名筛选
IEnumerable directories=foldersFilter.Split(',).SelectMany(模式=>sourceDirectory.EnumerateDirectories(模式,SearchOption.AllDirectories));
列表文件=新列表();
files.AddRange(directories.SelectMany(dir=>fileTypesFilter.Split(',).SelectMany(pattern=>dir.EnumerateFiles(pattern,SearchOption.AllDirectories)));
//拾取根文件
files.AddRange(fileTypesFilter.Split(',).SelectMany(pattern=>sourceDirectory.EnumerateFiles(fileTypesFilter,SearchOption.TopDirectoryOnly));
//按扩展过滤
IEnumerable files2=fileTypesFilter.Split(',).SelectMany(pattern=>sourceDirectory.EnumerateFiles(pattern,SearchOption.AllDirectories));
}
正如我在评论中提到的,虽然Mikael Svenson的助手方法是很小的解决方案,但是如果你再次尝试为一次性项目做一些事情,请考虑LINQ扩展<强> .Union()。这允许您将两个可枚举序列连接在一起。在您的情况下,代码如下所示:
List<string> result = Directory.EnumerateFiles(path,"*.mp3", SearchOption.AllDirectories)
.Union(Directory.EnumerateFiles(path, ".wma", SearchOption.AllDirectories)).ToList();
List result=Directory.EnumerateFiles(路径“*.mp3”、SearchOption.AllDirectories)
.Union(Directory.EnumerateFiles(路径“.wma”,SearchOption.AllDirectories)).ToList();
这将在一行中创建并填充结果列表。最优雅的方法可能是:
var directory = new DirectoryInfo(path);
var masks = new[] { "*.mp3", "*.wav" };
var files = masks.SelectMany(directory.EnumerateFiles);
但是它可能不是最有效的。对于使用与GUI打开对话框相同的文件扩展名列表字符串进行过滤,例如:
".exe,.pdb".Split(',', ';', '|').SelectMany(_ => Directory.EnumerateFiles(".", "*" + _, searchOptions)
打包:
public static IEnumerable<string> EnumerateFilesFilter(string path, string filesFilter, SearchOption searchOption = SearchOption.TopDirectoryOnly)
{
return filesFilter.Split(',', ';', '|').SelectMany(_ => Directory.EnumerateFiles(path, "*" + _, searchOption));
}
公共静态IEnumerable EnumerateFileFilter(字符串路径、字符串文件筛选器、SearchOption SearchOption=SearchOption.TopDirectoryOnly)
{
返回filesFilter.Split(“,”,“;”,“|”).SelectMany(=>Directory.EnumerateFiles(路径,“*”+,searchOption));
}
我这样解决了这个问题:
string[] formats = {".mp3", ".wma", ".mp4"};
foreach (var file in Directory.EnumerateFiles(folder, "*.*", SearchOption.AllDirectories).Where(x => formats.Any(x.EndsWith)))
{
// TODO...
}
如果要与*
进行字符串比较,则需要删除它们。另一个建议是使用允许不区分大小写检查的重载。可能最好使用哈希集和不区分大小写的比较。您需要包含点(.mp3)。使用string.ToLower()来处理大小写。@Hans,这个点是对的,但是ToLower()会比普通的大小写好吗?只是一个选择:你还需要“.mp3”,而不是“mp3”。谢谢你的作品完美。。。在我的情况下,我需要在之前添加.ToArray()。其中。。。如果没有这个,LINQ查询就不起作用了。你应该考虑并行运行每个扩展搜索。我在回答中创建了一些有用的助手方法。这是一个非常古老的问题(已经由@MikaelSvenson适当地回答了),但另一个选项是使用可枚举扩展名.Union(),如:foreach(Directory.EnumerateFiles(path,.mp3),SearchOption.AllDirectories)。Union(Directory.EnumerateFiles(path,.wma),SearchOption.AllDirectories)){…}感谢您的良好实现。什么是好的(高效的)最终在WPF屏幕上显示结果的方法?我计划使用您的并行方法来获取文件。如果我使用foreach迭代结果并将其存储在列表中,然后将其加载到屏幕上会怎么样?您可以只绑定到任一方法的输出,因为绑定将为您枚举所有结果。无需首先将其存储在单独的列表中。m最有效的方法是开始显示枚举的项目。我不是WPF专家,但我想是的
public static IEnumerable<string> EnumerateFilesFilter(string path, string filesFilter, SearchOption searchOption = SearchOption.TopDirectoryOnly)
{
return filesFilter.Split(',', ';', '|').SelectMany(_ => Directory.EnumerateFiles(path, "*" + _, searchOption));
}
string[] formats = {".mp3", ".wma", ".mp4"};
foreach (var file in Directory.EnumerateFiles(folder, "*.*", SearchOption.AllDirectories).Where(x => formats.Any(x.EndsWith)))
{
// TODO...
}