我试图使用Directory.GetFiles()方法检索多种类型的文件列表,如mp3的和jpg的。以下两种方法我都试过了,但都没有成功:
Directory.GetFiles("C:\\path", "*.mp3|*.jpg", SearchOption.AllDirectories);
Directory.GetFiles("C:\\path", "*.mp3;*.jpg", SearchOption.AllDirectories);
有没有办法一次就能搞定?
我试图使用Directory.GetFiles()方法检索多种类型的文件列表,如mp3的和jpg的。以下两种方法我都试过了,但都没有成功:
Directory.GetFiles("C:\\path", "*.mp3|*.jpg", SearchOption.AllDirectories);
Directory.GetFiles("C:\\path", "*.mp3;*.jpg", SearchOption.AllDirectories);
有没有办法一次就能搞定?
当前回答
我想知道为什么有这么多“解决方案”张贴?
如果我对GetFiles如何工作的新手理解是正确的,那么只有两个选项,上面的任何解决方案都可以归结为:
GetFiles,然后是filter:速度很快,但在应用过滤器之前,由于存储开销,是内存杀手 在GetFiles时过滤:设置的过滤器越多,速度越慢,但由于没有存储开销,内存使用量就越低。这在上面的一篇文章中有一个令人印象深刻的基准测试:每个过滤器选项都会导致一个单独的GetFile-operation,因此硬盘的同一部分会被读取几次。
在我看来,选项1)是更好的,但使用SearchOption。像C:\这样的文件夹中的所有目录会占用大量内存。 因此,我将创建一个递归子方法,使用选项1遍历所有子文件夹)
这应该导致每个文件夹上只有1个getfiles -操作,因此速度很快(选项1),但只使用少量内存,因为在每个子文件夹读取后应用过滤器->开销在每个子文件夹后删除。
如果我说错了,请指正。就像我说的,我对编程很陌生,但我想对事情有更深入的了解,最终在这方面做得很好:)
其他回答
for
var exts = new[] { "mp3", "jpg" };
你可以:
public IEnumerable<string> FilterFiles(string path, params string[] exts) {
return
Directory
.EnumerateFiles(path, "*.*")
.Where(file => exts.Any(x => file.EndsWith(x, StringComparison.OrdinalIgnoreCase)));
}
不要忘记新的。net 4目录。EnumerateFiles用于性能提升(目录和文件的区别是什么?EnumerateFiles vs Directory.GetFiles?) “IgnoreCase”应该比“ToLower”(。EndsWith("aspx", stringcompare . ordinalignorecase)而不是。tolower ().EndsWith("aspx"))
但EnumerateFiles的真正好处体现在你拆分过滤器并合并结果时:
public IEnumerable<string> FilterFiles(string path, params string[] exts) {
return
exts.Select(x => "*." + x) // turn into globs
.SelectMany(x =>
Directory.EnumerateFiles(path, x)
);
}
如果你不需要将它们转换为glob(即exts = new[] {"*.mp3", "*.jpg"}),它会变得更快一些。
基于以下LinqPad测试的性能评估(注意:Perf只是重复委托10000次) https://gist.github.com/zaus/7454021
(从'duplicate'重新发布和扩展,因为这个问题特别要求没有LINQ:多个文件扩展searchPattern for System.IO.Directory.GetFiles)
让你想要的扩展名为一个字符串,即“.mp3.jpg.wma.wmf”,然后检查每个文件是否包含你想要的扩展名。 这适用于。net 2.0,因为它不使用LINQ。
string myExtensions=".jpg.mp3";
string[] files=System.IO.Directory.GetFiles("C:\myfolder");
foreach(string file in files)
{
if(myExtensions.ToLower().contains(System.IO.Path.GetExtension(s).ToLower()))
{
//this file has passed, do something with this file
}
}
这种方法的优点是你可以添加或删除扩展,而不需要编辑代码,即添加png图像,只需写myExtensions=".jpg.mp3.png"。
另一种使用Linq的方式,但是不需要返回所有内容并在内存中过滤。
var files = Directory.GetFiles("C:\\path", "*.mp3", SearchOption.AllDirectories).Union(Directory.GetFiles("C:\\path", "*.jpg", SearchOption.AllDirectories));
它实际上是对GetFiles()的2次调用,但我认为这与问题的精神是一致的,并以一个可枚举的形式返回它们。
Let
var set = new HashSet<string>(
new[] { ".mp3", ".jpg" },
StringComparer.OrdinalIgnoreCase); // ignore case
var dir = new DirectoryInfo(path);
Then
dir.EnumerateFiles("*.*", SearchOption.AllDirectories)
.Where(f => set.Contains(f.Extension));
or
from file in dir.EnumerateFiles("*.*", SearchOption.AllDirectories)
from ext in set // makes sense only if it's just IEnumerable<string> or similar
where String.Equals(ext, file.Extension, StringComparison.OrdinalIgnoreCase)
select file;
/// <summary>
/// Returns the names of files in a specified directories that match the specified patterns using LINQ
/// </summary>
/// <param name="srcDirs">The directories to seach</param>
/// <param name="searchPatterns">the list of search patterns</param>
/// <param name="searchOption"></param>
/// <returns>The list of files that match the specified pattern</returns>
public static string[] GetFilesUsingLINQ(string[] srcDirs,
string[] searchPatterns,
SearchOption searchOption = SearchOption.AllDirectories)
{
var r = from dir in srcDirs
from searchPattern in searchPatterns
from f in Directory.GetFiles(dir, searchPattern, searchOption)
select f;
return r.ToArray();
}