Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中最快的方法是在包含20000多个文件的目录中查找文件_C#_.net_File Io - Fatal编程技术网

C#中最快的方法是在包含20000多个文件的目录中查找文件

C#中最快的方法是在包含20000多个文件的目录中查找文件,c#,.net,file-io,C#,.net,File Io,我有一个每天晚上运行的任务,从根目录下有20000多个子文件夹的目录中提取xml文件。以下是结构的外观: rootFolder/someFolder/someSubFolder/xml/myFile.xml rootFolder/someFolder/someSubFolder1/xml/myFile1.xml rootFolder/someFolder/someSubFolderN/xml/myFile2.xml rootFolder/someFolder1 rootFolder/someFo

我有一个每天晚上运行的任务,从根目录下有20000多个子文件夹的目录中提取xml文件。以下是结构的外观:

rootFolder/someFolder/someSubFolder/xml/myFile.xml
rootFolder/someFolder/someSubFolder1/xml/myFile1.xml
rootFolder/someFolder/someSubFolderN/xml/myFile2.xml
rootFolder/someFolder1
rootFolder/someFolderN
因此,综上所述,结构总是相同的——一个根文件夹,然后是两个子文件夹,然后是xml目录,然后是xml文件。 我只知道根文件夹和xml目录的名称

下面的代码遍历所有目录,速度非常慢。有没有关于如何优化搜索的建议,特别是在已知目录结构的情况下

string[] files = Directory.GetFiles(@"\\somenetworkpath\rootFolder", "*.xml", SearchOption.AllDirectories);

是否有与xml文件夹相同级别的其他目录?如果是这样的话,你可能会加快搜索速度,如果你自己做的话,并从搜索中消除这个级别

        System.IO.DirectoryInfo root = new System.IO.DirectoryInfo(rootPath);
        List<System.IO.FileInfo> xmlFiles=new List<System.IO.FileInfo>();

        foreach (System.IO.DirectoryInfo subDir1 in root.GetDirectories())
        {
            foreach (System.IO.DirectoryInfo subDir2 in subDir1.GetDirectories())
            {
                System.IO.DirectoryInfo xmlDir = new System.IO.DirectoryInfo(System.IO.Path.Combine(subDir2.FullName, "xml"));

                if (xmlDir.Exists)
                {
                    xmlFiles.AddRange(xmlDir.GetFiles("*.xml"));
                }
            }
        }
System.IO.DirectoryInfo root=new System.IO.DirectoryInfo(rootPath);
List xmlFiles=新列表();
foreach(root.GetDirectories()中的System.IO.DirectoryInfo subDir1)
{
foreach(subDir1.GetDirectories()中的System.IO.DirectoryInfo subDir2)
{
System.IO.DirectoryInfo xmlDir=new System.IO.DirectoryInfo(System.IO.Path.Combine(subdri2.FullName,“xml”);
if(xmlDir.Exists)
{
AddRange(xmlDir.GetFiles(“*.xml”);
}
}
}

在C#中,我想不出比这更快的方法了,但是您是否为该文件系统启用了索引功能?

您最有可能使用GetDirectory,首先获取“第一个子文件夹”列表,循环浏览这些目录,然后对子文件夹重复该过程,循环遍历它们,最后查找xml文件夹,最后搜索.xml文件

现在,对于性能来说,速度会有所不同,但是首先搜索目录,然后访问文件应该会有很大帮助

更新

好的,我做了一个快速的测试,你实际上可以比我想象的更进一步地优化它

下面的代码片段将搜索目录结构,并在整个目录树中找到所有“xml”文件夹

string startPath = @"C:\Testing\Testing\bin\Debug";
string[] oDirectories = Directory.GetDirectories(startPath, "xml", SearchOption.AllDirectories);
Console.WriteLine(oDirectories.Length.ToString());
foreach (string oCurrent in oDirectories)
    Console.WriteLine(oCurrent);
Console.ReadLine();
如果你把它放到一个测试控制台应用程序中,你会看到它输出结果


现在,一旦你有了这个,只需在找到的每个目录中查找.xml文件。

我能看到的唯一不同的方法是改变暴力强度搜索,并使用一些第三方或操作系统索引例程来加快返回速度。这样,搜索就可以从你的应用程序离线完成


但我也建议您尽可能寻找更好的方法来构造数据。

FindFirstFile
/
FindNextFile
/
FindClose
上使用p/Invoke,并避免创建大量FileInfo实例的开销


但这将是一项艰难的工作(您必须自己处理文件、目录和递归)。因此,请尝试一些简单的方法(Directory.GetFiles()、Directory.GetDirectories())来开始工作,并使其正常工作。如果速度太慢,请查看备选方案(但总是测量,太容易使其变慢)。

我创建了一个递归方法
GetFolders
,使用
并行方法。ForEach
查找所有名为变量
yourKeyword

List<string> returnFolders = new List<string>();
object locker = new object();

Parallel.ForEach(subFolders, subFolder =>
{
    if (subFolder.ToUpper().EndsWith(yourKeyword))
    {
        lock (locker)
        {
            returnFolders.Add(subFolder);
        }
    }
    else
    {
        lock (locker)
        {
            returnFolders.AddRange(GetFolders(Directory.GetDirectories(subFolder)));
        }
    }
});

return returnFolders;
List returnFolders=new List();
对象锁定器=新对象();
Parallel.ForEach(子文件夹,子文件夹=>
{
if(子文件夹.ToUpper().EndsWith(yourKeyword))
{
锁(储物柜)
{
returnFolders.Add(子文件夹);
}
}
其他的
{
锁(储物柜)
{
returnFolders.AddRange(GetFolders(Directory.GetDirectories(subFolder));
}
}
});
返回文件夹;

根据您的需要和配置,您可以使用Windows搜索索引:


根据您的配置,这可以大大提高性能。

对于文件和目录搜索,我希望提供具有广泛搜索机会的多线程.NET库。 您可以在GitHub上找到有关库的所有信息: 如果您想下载,可以在以下位置下载: 如果你有任何问题,请问他们

工作非常快。你自己检查一下

这是一个演示示例,说明了如何使用它:

class Searcher
{
    private static object locker = new object(); 

    private FileSearcher searcher;

    List<FileInfo> files;

    public Searcher()
    {
        files = new List<FileInfo>();
    }

    public void Startsearch()
    {
        CancellationTokenSource tokenSource = new CancellationTokenSource();

        searcher = new FileSearcher(@"C:\", (f) =>
        {
            return Regex.IsMatch(f.Name, @".*[Dd]ragon.*.jpg$");
        }, tokenSource);  


        searcher.FilesFound += (sender, arg) => 
        {
            lock (locker) // using a lock is obligatorily
            {
                arg.Files.ForEach((f) =>
                {
                    files.Add(f);
                    Console.WriteLine($"File location: {f.FullName}, \nCreation.Time: {f.CreationTime}");
                });

                if (files.Count >= 10) 
                    searcher.StopSearch();
            }
        };

        searcher.SearchCompleted += (sender, arg) => 
        {
            if (arg.IsCanceled) 
                Console.WriteLine("Search stopped.");
            else
                Console.WriteLine("Search completed.");

            Console.WriteLine($"Quantity of files: {files.Count}"); 
        };

        searcher.StartSearchAsync();
    }
}
类搜索器
{
私有静态对象锁定器=新对象();
私有文件搜索器;
列出文件;
公共搜索者()
{
文件=新列表();
}
公共无效Startsearch()
{
CancellationTokenSource tokenSource=新的CancellationTokenSource();
searcher=newfilesearcher(@“C:\”,(f)=>
{
返回Regex.IsMatch(f.Name,@“*[Dd]ragon.*.jpg$”;
},来源);
searcher.FilesFound+=(发件人,arg)=>
{
锁(储物柜)//使用锁是强制性的
{
arg.Files.ForEach((f)=>
{
添加(f);
WriteLine($“文件位置:{f.FullName},\n创建时间:{f.CreationTime}”);
});
如果(files.Count>=10)
searcher.StopSearch();
}
};
searcher.SearchCompleted+=(发件人,arg)=>
{
如果(参数已取消)
控制台.WriteLine(“搜索已停止”);
其他的
Console.WriteLine(“搜索已完成”);
WriteLine($“文件数量:{files.Count}”);
};
startsearchsync();
}
}
这是其他示例的一部分:

***
List<string> folders = new List<string>
{
  @"C:\Users\Public",
  @"C:\Windows\System32",
  @"D:\Program Files",
  @"D:\Program Files (x86)"
}; // list of search directories

List<string> keywords = new List<string> { "word1", "word2", "word3" }; // list of search keywords

FileSearcherMultiple multipleSearcher = new FileSearcherMultiple(folders, (f) =>
{
  if (f.CreationTime >= new DateTime(2015, 3, 15) &&
     (f.Extension == ".cs" || f.Extension == ".sln"))
    foreach (var keyword in keywords)
      if (f.Name.Contains(keyword))
        return true;
  return false;
}, tokenSource, ExecuteHandlers.InCurrentTask, true);  
***
***
列表文件夹=新列表
{
@“C:\Users\Public”,
@“C:\Windows\System32”,
@“D:\程序文件”,
@“D:\Program Files(x86)”
}; // 搜索目录列表
列表关键字=新列表{“word1”、“word2”、“word3”};//搜索关键字列表
文件搜索多个多语言
List<FileInfo> files = FileSearcher.GetFilesFast(@"C:\Users", "*.xml");
    private void btnSearch_Click(object sender, EventArgs e)
    {
        string userinput = txtInput.Text;

        string sourceFolder = @"C:\mytestDir\";
        string searchWord = txtInput.Text + ".pdf";
        string filePresentCK = sourceFolder + searchWord;
        if (File.Exists(filePresentCK))
            {

                pdfViewer1.LoadFromFile(sourceFolder+searchWord);
            }
            else if(! File.Exists(filePresentCK))
            {
                MessageBox.Show("Unable to Find file :" + searchWord);
            }

        txtInput.Clear();

    }// end of btnSearch method