Question

is it possible to extract 'some' properties from a given file without using System.IO.FileInfo at all?

I mean, I love using FileInfo in cases where I just have a few files to deal with, but if, for example, I want to grab a list of file names from, let's say, half a million files and I decide to use FileInfo... it takes for-darn-ever!

I suspect that FileInfo loads a bunch of other stuff about that file into memory (is that correct?). If so, I feel like there should be a faster way to, say, just grab name or file extension.

On the other hand, I could just use Directory.GetFiles(myPath), but this gives me an array with the full paths for every file, while I just need the name per file! (I guess I could parse the path string to extract the name from it... would that be faster than using FileInfo?)

What other alternatives are out there if I want to accomplish this (grab the name of the file, or grab the file extension) faster?

Thank you very much!!

Was it helpful?

Solution

You're looking for the methods in the Path class.

Specifically, Path.GetFileName() and Path.GetExtension().

OTHER TIPS

Inspired by your question, I compared FileInfo and FileSystemObject. I measured how long both take to traverse a SSD drive.

In essence, FileInfo was about three times faster than FileSystemObject.

I repeated the measurements on my system to rule-out caching effects:

test FileInfo Files: 489557 Directories: 66023
FileInfo traversal needed 12,07s

test FileSystemObject. Files: 489557 Directories: 66023 
FileInfo traversal needed 38,59s

It might be worthwile to try using the Windows API. But calling and parameter passing have to pay a performance fee due to Marshalling.

A home grown C utility needs about 8s to scan the SSD.

The code:

using System;
using System.Linq;

using Scripting;
using System.Diagnostics;
using System.IO;

namespace akTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch watch = new Stopwatch();

            watch.Start();
            testFileInfo(@"c:\");
            watch.Stop();
            o("FileInfo traversal needed " + (watch.ElapsedMilliseconds/1000.0).ToString("#.##") + "s");

            watch.Start();
            testFSO(@"c:\");
            watch.Stop();
            o("FileInfo traversal needed " + (watch.ElapsedMilliseconds / 1000.0).ToString("#.##") + "s");

            o("");
            o("Ciao!");
        }

        static void o(string s)
        {
            Console.WriteLine(s);
        }

        static void testFileInfo(string dir)
        {
            DirectoryInfo di = new DirectoryInfo(dir);
            long fileCount = 0;
            long dirCount = 0;
            long calls = 0;

            o("Testing FileInfo");

            WalkDirectoryTree(di, ref fileCount, ref dirCount, ref calls);

            o("testFileInfo completed. Files: " + fileCount + " Directories: " + dirCount + " Calls: " + calls);
        }

        static void testFSO(string dir)
        {
            FileSystemObject fso = new FileSystemObject();
            Folder folder = fso.GetFolder(dir);

            long fileCount = 0;
            long dirCount = 0;
            long calls = 0;

            o("Testing FSO");

            WalkDirectoryTree(folder, ref fileCount, ref dirCount, ref calls);

            o("testFSO completed. Files: " + fileCount + " Directories: " + dirCount + " Calls: " + calls);
        }

        static void WalkDirectoryTree(DirectoryInfo root, ref long fileCount, ref long dirCount, ref long calls)
        {
            FileInfo[] files = null;
            DirectoryInfo[] subDirs = null;

            if (++calls % 10000 == 0)
                o("" + calls);

            try
            {
                files = root.GetFiles("*.*");

                if (files != null)
                {
                    fileCount += files.Count();
                    subDirs = root.GetDirectories();
                    dirCount += subDirs.Count();

                    foreach (DirectoryInfo dirInfo in subDirs)
                    {
                        WalkDirectoryTree(dirInfo, ref fileCount, ref dirCount, ref calls);
                    }
                }
            }
            catch (Exception)
            {
            }
        }


        static void WalkDirectoryTree(Folder root, ref long fileCount, ref long dirCount, ref long calls)
        {
            Files files = null;
            Folders subDirs = null;

            if (++calls % 10000 == 0)
                o("" + calls);

            try
            {
                files = root.Files;

                if (files != null)
                {
                    fileCount += files.Count;
                    subDirs = root.SubFolders;
                    dirCount += subDirs.Count;

                    foreach (Folder fd in subDirs)
                    {
                        WalkDirectoryTree(fd, ref fileCount, ref dirCount, ref calls);
                    }
                }
            }
            catch (Exception)
            {
            }
        }
    }
}

You could use Path.GetFilename to get the file name if that is all you are interested in.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top