特定扩展名的 Directory.GetFiles

77

有没有简化这个Linq表达式的方法,或者有更好的方法来完成这个任务?

Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories)
         .Where(s => s.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) ||
                     s.EndsWith(".gif", StringComparison.OrdinalIgnoreCase) ||
                     s.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ||
                     ...);
基本上,我想返回特定扩展名的所有文件。不幸的是,这种方法并不是非常灵活。我更希望能够将扩展名添加到列表中,并让Directory.GetFiles返回这些扩展名。这可能吗?

2
可以使用多个过滤器调用Directory.GetFiles吗? - Jeffrey Knight
3个回答

127

如果你想在LINQ中进行筛选,可以像这样操作:

var ext = new List<string> { "jpg", "gif", "png" };
var myFiles = Directory
    .EnumerateFiles(dir, "*.*", SearchOption.AllDirectories)
    .Where(s => ext.Contains(Path.GetExtension(s).TrimStart(".").ToLowerInvariant()));
现在ext包含了允许的扩展名列表;你可以根据需要添加或删除其中的项目以进行灵活的筛选。
现在ext包含了允许的扩展名列表;你可以根据需要添加或删除其中的项目以进行灵活的筛选。

我可以执行测试,但您知道哪种测试更有效吗? - XSL
有趣的是它能工作...从GetFiles的文档中看,它似乎不会像正则表达式一样接受|。文档说它只识别*?,但是,如果它能工作,那就好了 =) - Tyler Lee
2
注意:在运行.NET 4.5的Win7 x64上似乎无法正常工作。由于管道,会抛出“路径中存在非法字符”的异常。 - Simon Whitehead
@SimonWhitehead 没关系,我误解了 Microsoft 网站上一篇帖子中的一段代码,其中一个同名方法已经在内部解释了这些管道。我删除了解决方案中不起作用的部分(并且只检查了第一个 SSL)。 - Sergey Kalinichenko
2
路过的朋友请注意:如@nekizalb所述,您可能会从较新的.NET 4.0 Directory.EnumerateFiles中获得性能提升。 - drzaus

33

不是已经有Directory.GetFiles(String, String)的重载函数可以做到这个吗?你只需要使用Directory.GetFiles(dir, "*.jpg", SearchOption.AllDirectories)就可以了。

如果你想把它们放在一个列表中,那么只需要用一个变量来迭代列表,并将结果聚合到一个总的结果集中,比逐个指定它们要清晰得多。=)

类似这样的代码...

foreach(String fileExtension in extensionList){
    foreach(String file in Directory.GetFiles(dir, fileExtension, SearchOption.AllDirectories)){
        allFiles.Add(file);
    }
}

对于.NET 4+:如果您的目录很大,使用EnumerateFiles而不是GetFiles可能会更高效。

谢谢。我喜欢这个想法,但是我不确定在循环中多次调用GetFiles会有多高的效率。 - XSL
请参阅有关EnumerateFiles方法的附加注释。 - Tyler Lee
啊,好吧。总有一种选择是在内部的foreach之前运行一次GetFiles并存储结果,然后在foreach中使用该存储的列表。 - Tyler Lee
6
请注意,在使用通配符“”时,有可能会破坏原本想要实现的逻辑。例如,你有两个文件Test1.xls和Test2.xlsx,如果你使用过滤器“.xls”来筛选xls文件,Directory.GetFiles会返回既包括xls文件也包括xlsx文件。[欲了解更多信息,请参阅MSDN:http://msdn.microsoft.com/en-us/library/ms143316%28v=vs.110%29.aspx] - kiran
1
实际上,xls和xlsx是现代Excel可以读取的相同文件? - ina
显示剩余2条评论

13
我本可以只用一行代码来完成这个任务。
List<string> imageFiles = Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories).Where(file => new string[] { ".jpg", ".gif", ".png" }.Contains(Path.GetExtension(file))).ToList();

7
当然,这个方法有效,但是你传递给.Where()的lambda表达式会在每次调用时创建一个string[]数组;也就是说,对于dir下的每个文件都会创建一个数组。如果dir@"C:\",那么可能会创建成千上万个短暂的“垃圾”数组。我认为值得在.Where()之外定义数组,即使这意味着要写那可怕的第二行代码。 - Lance U. Matthews

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接