我正在尝试使用该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);
有没有办法在一个电话中做到这一点?
Answers:
对于.NET 4.0及更高版本,
var files = Directory.EnumerateFiles("C:\\path", "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));
对于早期版本的.NET,
var files = Directory.GetFiles("C:\\path", "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));
编辑: 请阅读评论。Paul Farry建议的改进以及Christian.K指出的内存/性能问题都很重要。
s.ToLower().Endswith...
s.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase)
Directory.GetFiles
使用Directory.EnumerateFiles
,msdn.microsoft.com/en-us/library/dd383571.aspx,这将避免内存问题是@ Christian.K提到。
这个怎么样:
private static string[] GetFiles(string sourceFolder, string filters, System.IO.SearchOption searchOption)
{
return filters.Split('|').SelectMany(filter => System.IO.Directory.GetFiles(sourceFolder, filter, searchOption)).ToArray();
}
我在这里(在评论中)找到了它:http : //msdn.microsoft.com/en-us/library/wz42302f.aspx
Parallel.ForEach
并行地获取它们
如果您有大量要检查的扩展,可以使用以下方法。我不想创建很多OR语句,所以我修改了lette的内容。
string supportedExtensions = "*.jpg,*.gif,*.png,*.bmp,*.jpe,*.jpeg,*.wmf,*.emf,*.xbm,*.ico,*.eps,*.tif,*.tiff,*.g01,*.g02,*.g03,*.g04,*.g05,*.g06,*.g07,*.g08";
foreach (string imageFile in Directory.GetFiles(_tempDirectory, "*.*", SearchOption.AllDirectories).Where(s => supportedExtensions.Contains(Path.GetExtension(s).ToLower())))
{
//do work here
}
Path.GetExtension
返回“ .ext”,而不是“ * .ext”(至少在3.5+中)。
.abc
,并且supportedExtensions包含.abcd
。将匹配,尽管不匹配。要解决:supportedExtensions = ".jpg|.abcd|";
用.Contains(Path.GetExtension(s).ToLower() + "|")
。也就是说,在测试中包括分隔符。重要说明:您的分隔符也必须在supportedExceptions中的LAST条目之后。
对于
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)));
}
Directory.EnumerateFiles
来提高性能(Directory.EnumerateFiles与Directory.GetFiles之间有什么区别?).EndsWith("aspx", StringComparison.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)
);
}
如果您不必将它们变成全局(即exts = new[] {"*.mp3", "*.jpg"}
已经),它将变得更快。
基于以下LinqPad测试的性能评估(注意:Perf
仅将委托重复10000次)
https://gist.github.com/zaus/7454021
(从'duplicate'重新发布并扩展,因为该问题明确要求没有LINQ:System.IO.Directory.GetFiles的多个文件扩展名searchPattern)
.FilterFiles(path, "jpg", "gif")
)是否比“显式全局”(即.FilterFiles(path, "*.jpg", "*.gif")
)更好。
我知道这是一个老问题,但是LINQ:(.NET40 +)
var files = Directory.GetFiles("path_to_files").Where(file => Regex.IsMatch(file, @"^.+\.(wav|mp3|txt)$"));
file.ToLower()
来轻松匹配大写扩展名。为什么不先提取扩展名,所以Regex不必检查整个路径: Regex.IsMatch(Path.GetExtension(file).ToLower(), @"\.(wav|mp3|txt)");
还有一个下降的解决方案,似乎没有任何内存或性能开销,而且非常优雅:
string[] filters = new[]{"*.jpg", "*.png", "*.gif"};
string[] filePaths = filters.SelectMany(f => Directory.GetFiles(basePath, f)).ToArray();
使用Linq的另一种方法,但不必返回所有内容并对其进行过滤。
var files = Directory.GetFiles("C:\\path", "*.mp3", SearchOption.AllDirectories).Union(Directory.GetFiles("C:\\path", "*.jpg", SearchOption.AllDirectories));
实际上是对的2个调用GetFiles()
,但我认为这与问题的精神相一致,并以一个可枚举的形式返回。
不。请尝试以下操作:
List<string> _searchPatternList = new List<string>();
...
List<string> fileList = new List<string>();
foreach ( string ext in _searchPatternList )
{
foreach ( string subFile in Directory.GetFiles( folderName, ext )
{
fileList.Add( subFile );
}
}
// Sort alpabetically
fileList.Sort();
// Add files to the file browser control
foreach ( string fileName in fileList )
{
...;
}
摘自:http : //blogs.msdn.com/markda/archive/2006/04/20/580075.aspx
让
var set = new HashSet<string> { ".mp3", ".jpg" };
然后
Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)
.Where(f => set.Contains(
new FileInfo(f).Extension,
StringComparer.OrdinalIgnoreCase));
要么
from file in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)
from ext in set
where String.Equals(ext, new FileInfo(file).Extension, StringComparison.OrdinalIgnoreCase)
select file;
我无法使用.Where
method,因为我正在.NET Framework 2.0中编程(仅.NET Framework 3.5+支持Linq)。
下面的代码不区分大小写(所以.CaB
也.cab
将列出)。
string[] ext = new string[2] { "*.CAB", "*.MSU" };
foreach (string found in ext)
{
string[] extracted = Directory.GetFiles("C:\\test", found, System.IO.SearchOption.AllDirectories);
foreach (string file in extracted)
{
Console.WriteLine(file);
}
}
以下函数搜索多个模式,以逗号分隔。您也可以指定排除,例如:“!web.config”将搜索所有文件,而排除“ web.config”。模式可以混合。
private string[] FindFiles(string directory, string filters, SearchOption searchOption)
{
if (!Directory.Exists(directory)) return new string[] { };
var include = (from filter in filters.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) where !string.IsNullOrEmpty(filter.Trim()) select filter.Trim());
var exclude = (from filter in include where filter.Contains(@"!") select filter);
include = include.Except(exclude);
if (include.Count() == 0) include = new string[] { "*" };
var rxfilters = from filter in exclude select string.Format("^{0}$", filter.Replace("!", "").Replace(".", @"\.").Replace("*", ".*").Replace("?", "."));
Regex regex = new Regex(string.Join("|", rxfilters.ToArray()));
List<Thread> workers = new List<Thread>();
List<string> files = new List<string>();
foreach (string filter in include)
{
Thread worker = new Thread(
new ThreadStart(
delegate
{
string[] allfiles = Directory.GetFiles(directory, filter, searchOption);
if (exclude.Count() > 0)
{
lock (files)
files.AddRange(allfiles.Where(p => !regex.Match(p).Success));
}
else
{
lock (files)
files.AddRange(allfiles);
}
}
));
workers.Add(worker);
worker.Start();
}
foreach (Thread worker in workers)
{
worker.Join();
}
return files.ToArray();
}
用法:
foreach (string file in FindFiles(@"D:\628.2.11", @"!*.config, !*.js", SearchOption.AllDirectories))
{
Console.WriteLine(file);
}
List<string> FileList = new List<string>();
DirectoryInfo di = new DirectoryInfo("C:\\DirName");
IEnumerable<FileInfo> fileList = di.GetFiles("*.*");
//Create the query
IEnumerable<FileInfo> fileQuery = from file in fileList
where (file.Extension.ToLower() == ".jpg" || file.Extension.ToLower() == ".png")
orderby file.LastWriteTime
select file;
foreach (System.IO.FileInfo fi in fileQuery)
{
fi.Attributes = FileAttributes.Normal;
FileList.Add(fi.FullName);
}
file.Extension.ToLower()
是坏习惯。
String.Equals(a, b, StringComparison.OrdinalIgnoreCase)
在.NET 2.0中(无Linq):
public static List<string> GetFilez(string path, System.IO.SearchOption opt, params string[] patterns)
{
List<string> filez = new List<string>();
foreach (string pattern in patterns)
{
filez.AddRange(
System.IO.Directory.GetFiles(path, pattern, opt)
);
}
// filez.Sort(); // Optional
return filez; // Optional: .ToArray()
}
然后使用它:
foreach (string fn in GetFilez(path
, System.IO.SearchOption.AllDirectories
, "*.xml", "*.xml.rels", "*.rels"))
{}
DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Contents/"));
//Using Union
FileInfo[] files = directory.GetFiles("*.xlsx")
.Union(directory
.GetFiles("*.csv"))
.ToArray();
只是找到了另一种方法。仍然不是一项手术,而是扔出去看看其他人对此有何看法。
private void getFiles(string path)
{
foreach (string s in Array.FindAll(Directory.GetFiles(path, "*", SearchOption.AllDirectories), predicate_FileMatch))
{
Debug.Print(s);
}
}
private bool predicate_FileMatch(string fileName)
{
if (fileName.EndsWith(".mp3"))
return true;
if (fileName.EndsWith(".jpg"))
return true;
return false;
}
关于什么
string[] filesPNG = Directory.GetFiles(path, "*.png");
string[] filesJPG = Directory.GetFiles(path, "*.jpg");
string[] filesJPEG = Directory.GetFiles(path, "*.jpeg");
int totalArraySizeAll = filesPNG.Length + filesJPG.Length + filesJPEG.Length;
List<string> filesAll = new List<string>(totalArraySizeAll);
filesAll.AddRange(filesPNG);
filesAll.AddRange(filesJPG);
filesAll.AddRange(filesJPEG);
将所需的扩展名设为一个字符串,即“ .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”。
s
/// <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();
}
我遇到了同样的问题,找不到正确的解决方案,所以我写了一个叫GetFiles的函数:
/// <summary>
/// Get all files with a specific extension
/// </summary>
/// <param name="extensionsToCompare">string list of all the extensions</param>
/// <param name="Location">string of the location</param>
/// <returns>array of all the files with the specific extensions</returns>
public string[] GetFiles(List<string> extensionsToCompare, string Location)
{
List<string> files = new List<string>();
foreach (string file in Directory.GetFiles(Location))
{
if (extensionsToCompare.Contains(file.Substring(file.IndexOf('.')+1).ToLower())) files.Add(file);
}
files.Sort();
return files.ToArray();
}
此功能只会调用Directory.Getfiles()
一次。
例如,调用如下函数:
string[] images = GetFiles(new List<string>{"jpg", "png", "gif"}, "imageFolder");
编辑:要获取具有多个扩展名的文件,请使用此文件:
/// <summary>
/// Get the file with a specific name and extension
/// </summary>
/// <param name="filename">the name of the file to find</param>
/// <param name="extensionsToCompare">string list of all the extensions</param>
/// <param name="Location">string of the location</param>
/// <returns>file with the requested filename</returns>
public string GetFile( string filename, List<string> extensionsToCompare, string Location)
{
foreach (string file in Directory.GetFiles(Location))
{
if (extensionsToCompare.Contains(file.Substring(file.IndexOf('.') + 1).ToLower()) &&& file.Substring(Location.Length + 1, (file.IndexOf('.') - (Location.Length + 1))).ToLower() == filename)
return file;
}
return "";
}
例如,调用如下函数:
string image = GetFile("imagename", new List<string>{"jpg", "png", "gif"}, "imageFolder");
我想知道为什么发布了这么多的“解决方案”?
如果我对GetFiles的工作原理的新手理解是正确的,那么只有两种选择,并且上述任何解决方案都可以归结为以下两种:
GetFiles,然后进行筛选:速度很快,但是由于存储开销直到应用了筛选器之后,它才成为内存杀手
GetFiles时过滤:设置的过滤器越慢,但由于没有存储开销,所以内存使用率低。
这在上面的一篇文章中以令人印象深刻的基准进行了解释:每个过滤器选项都会导致单独的GetFile操作,因此硬盘的同一部分将被读取多次。
我认为选项1)更好,但是在C:\等文件夹上使用SearchOption.AllDirectories会占用大量内存。
因此,我只想使用选项1)遍历所有子文件夹的递归子方法
这应该在每个文件夹上仅导致1个GetFiles操作,因此速度较快(选项1),但是仅使用少量内存,因为在每个子文件夹的读取之后应用过滤器->在每个子文件夹后删除了开销。
如果我错了,请纠正我。就像我说的那样,我对编程很陌生,但是想对事物有更深入的了解,以便最终精于此:)
如果您使用的是VB.NET(或将依赖项导入到C#项目中),则实际上存在一种方便的方法,该方法可以过滤多个扩展名:
Microsoft.VisualBasic.FileIO.FileSystem.GetFiles("C:\\path", Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, new string[] {"*.mp3", "*.jpg"});
在VB.NET中,可以通过My-namespace访问它:
My.Computer.FileSystem.GetFiles("C:\path", FileIO.SearchOption.SearchAllSubDirectories, {"*.mp3", "*.jpg"})
不幸的是,这些便利方法不像这样支持延迟评估的变体Directory.EnumerateFiles()
。
或者您可以将扩展字符串转换为String ^
vector <string> extensions = { "*.mp4", "*.avi", "*.flv" };
for (int i = 0; i < extensions.size(); ++i)
{
String^ ext = gcnew String(extensions[i].c_str());;
String^ path = "C:\\Users\\Eric\\Videos";
array<String^>^files = Directory::GetFiles(path,ext);
Console::WriteLine(ext);
cout << " " << (files->Length) << endl;
}