带有日期过滤器的C#GetFiles

Ben*_*Ben 5 c# performance

是否有更有效的方法从具有日期过滤器的目录中填充文件名列表?

目前,我这样做:

foreach (FileInfo flInfo in directory.GetFiles())
{
    DateTime yesterday = DateTime.Today.AddDays(-1);
    String name = flInfo.Name.Substring(3,4);
    DateTime creationTime = flInfo.CreationTime;
    if (creationTime.Date == yesterday.Date)
       yesterdaysList.Add(name);
}
Run Code Online (Sandbox Code Playgroud)

这遍历文件夹中的每个文件,我觉得应该有一个更有效的方法.

Oma*_*mar 18

第一解决方案

您可以使用LINQ:

List<string> yesterdaysList = directory.GetFiles().Where(x => x.CreationTime.Date == DateTime.Today.AddDays(-1))
                                                  .Select(x => x.Name)
                                                  .ToList();
Run Code Online (Sandbox Code Playgroud)

然后,您可以直接使用此名称列表.

二解决方案:

使其更快的另一个解决方案可能是:

DateTime yesterday = DateTime.Today.AddDays(-1); //initialize this variable only one time

foreach (FileInfo flInfo in directory.GetFiles()){
    if (flInfo.CreationTime.Date == yesterday.Date) //use directly flInfo.CreationTime and flInfo.Name without create another variable 
       yesterdaysList.Add(flInfo.Name.Substring(3,4));
}
Run Code Online (Sandbox Code Playgroud)

基准测试:

我使用这段代码做了一个基准测试:

class Program {
    static void Main( string[ ] args ) {
        DirectoryInfo directory = new DirectoryInfo( @"D:\Films" );
        Stopwatch timer = new Stopwatch( );
        timer.Start( );

        for ( int i = 0; i < 100000; i++ ) {
            List<string> yesterdaysList = directory.GetFiles( ).Where( x => x.CreationTime.Date == DateTime.Today.AddDays( -1 ) )
                                              .Select( x => x.Name )
                                              .ToList( );
        }

        timer.Stop( );
        TimeSpan elapsedtime = timer.Elapsed;
        Console.WriteLine( string.Format( "{0:00}:{1:00}:{2:00}", elapsedtime.Minutes, elapsedtime.Seconds, elapsedtime.Milliseconds / 10 ) );
        timer.Restart( );

        DateTime yesterday = DateTime.Today.AddDays( -1 ); //initialize this variable only one time
        for ( int i = 0; i < 100000; i++ ) {
            List<string> yesterdaysList = new List<string>( );

            foreach ( FileInfo flInfo in directory.GetFiles( ) ) {
                if ( flInfo.CreationTime.Date == yesterday.Date ) //use directly flInfo.CreationTime and flInfo.Name without create another variable 
                    yesterdaysList.Add( flInfo.Name.Substring( 3, 4 ) );
            }
        }


        timer.Stop( );
        elapsedtime = timer.Elapsed;
        Console.WriteLine( string.Format("{0:00}:{1:00}:{2:00}", elapsedtime.Minutes, elapsedtime.Seconds, elapsedtime.Milliseconds / 10));
        timer.Restart( );

        for ( int i = 0; i < 100000; i++ ) {
            List<string> list = new List<string>( );

            foreach ( FileInfo flInfo in directory.GetFiles( ) ) {
                DateTime _yesterday = DateTime.Today.AddDays( -1 );
                String name = flInfo.Name.Substring( 3, 4 );
                DateTime creationTime = flInfo.CreationTime;
                if ( creationTime.Date == _yesterday.Date )
                    list.Add( name );
            }
        }

        elapsedtime = timer.Elapsed;
        Console.WriteLine( string.Format( "{0:00}:{1:00}:{2:00}", elapsedtime.Minutes, elapsedtime.Seconds, elapsedtime.Milliseconds / 10 ) );
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

First solution: 00:19:84
Second solution: 00:17:64
Third solution: 00:19:91 //Your solution
Run Code Online (Sandbox Code Playgroud)

  • LINQ的效率低于foreach.它更干净,更容易阅读,但在幕后生成相同的循环并添加自己的开销. (3认同)
  • 在`GetFiles()`之后添加`.AsParallel()`并见证LINQ的强大功能 (2认同)
  • 没有帮助,GetFiles()在*single*thread上工作.良好的并行需要Directory.EnumerateFile (2认同)

usr*_*usr 6

我认为你是在提高文件系统级别的效率之后,而不是在C#级别.如果是这种情况,答案是否定的:没有办法告诉文件系统按日期过滤.它会不必要地归还一切.

如果你追求CPU效率:这是毫无意义的,因为将列表框中的项目添加到比过滤日期更加昂贵.优化代码不会产生任何结果.