Domanda

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!!

È stato utile?

Soluzione

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

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

Altri suggerimenti

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top