how to get the oldest file in a directory fast usi

2020-07-05 06:02发布

I have a directory with around 15-30 thousand files. I need to just pull the oldest one. In other words the one that was created first. Is there a quick way to do this using C#, other than loading them into a collection then sorting?

标签: c# .net file-io
9条回答
你好瞎i
2楼-- · 2020-07-05 06:19

If you control the directory (that is, if your programs are responsible for creating and maintaining all files in that directory), then you should consider tracking the metadata about each file separately; perhaps in a database.

In fact, the FileStream column type in SQL Server 2008 can help with this. You can create a table that contains columns for filename, create date, modify date, and a FileStream column for the content. You can find things like the oldest file by using indexes on the metadata columns. You can find the content by using the FileStream column.

查看更多
老娘就宠你
3楼-- · 2020-07-05 06:19

You can't do it without sorting but what you can do is make it fast.

Sorting by CreationTime can be slow because first accessing this property for each file involves interrogation of the file system.

Use A Faster Directory Enumerator that preserves more information about files while enumerating and allows to do sorting faster.

Code to compare performance:

static void Main(string[] args)
{
    var timer = Stopwatch.StartNew();

    var oldestFile = FastDirectoryEnumerator.EnumerateFiles(@"c:\windows\system32")
        .OrderBy(f => f.CreationTime).First();

    timer.Stop();

    Console.WriteLine(oldestFile);
    Console.WriteLine("FastDirectoryEnumerator - {0}ms", timer.ElapsedMilliseconds);
    Console.WriteLine();

    timer.Reset();
    timer.Start();

    var oldestFile2 = new DirectoryInfo(@"c:\windows\system32").GetFiles()
        .OrderBy(f => f.CreationTime).First();

    timer.Stop();

    Console.WriteLine(oldestFile2);
    Console.WriteLine("DirectoryInfo - {0}ms", timer.ElapsedMilliseconds);

    Console.WriteLine("Press ENTER to finish");
    Console.ReadLine();
}

For me it gives this:

VEN2232.OLB

FastDirectoryEnumerator - 27ms

VEN2232.OLB

DirectoryInfo - 559ms

查看更多
狗以群分
4楼-- · 2020-07-05 06:21

You will have to load the FileInfo objects into a collection & sort, but it's a one-liner:

FileSystemInfo fileInfo = new DirectoryInfo(directoryPath).GetFileSystemInfos()
    .OrderBy(fi => fi.CreationTime).First();

Ok, two lines because it's a long statement.

查看更多
闹够了就滚
5楼-- · 2020-07-05 06:27

Oddly enough, this worked perfectly on a directory of mine with 3000+ jpg files:

DirectoryInfo di = new DirectoryInfo(dpath);
FileInfo[] rgFiles = di.GetFiles("*.jpg");
FileInfo firstfile = rgFiles[0];
FileInfo lastfile = rgFiles[rgFiles.Length - 1];
DateTime oldestfiletime = firstfile.CreationTime;
DateTime newestfiletime = lastfile.CreationTime;
查看更多
手持菜刀,她持情操
6楼-- · 2020-07-05 06:28

Edit: Removed the sort and made it a function.

public static FileInfo GetOldestFile(string directory)
{
    if (!Directory.Exists(directory))
        throw new ArgumentException();

    DirectoryInfo parent = new DirectoryInfo(directory);
    FileInfo[] children = parent.GetFiles();
    if (children.Length == 0)
        return null;

    FileInfo oldest = children[0];
    foreach (var child in children.Skip(1))
    {
        if (child.CreationTime < oldest.CreationTime)
            oldest = child;
    }

    return oldest;
}
查看更多
等我变得足够好
7楼-- · 2020-07-05 06:33

The short answer is no. Windows file systems don't index files by date so there is no native way to do this, let alone a .net way without enumerating all of them.

查看更多
登录 后发表回答