3

I want to have Excel files whose extensions are xls and xlsx, with FileInfo object from a specific directory so I put the following code

    System.IO.FileInfo[] files = null;
        System.IO.DirectoryInfo dirInfo;

        dirInfo = new System.IO.DirectoryInfo(this.tbFolderTo.Text);

        string[] extensions = new[] { "*.xls", "*.xlsx" };
        List<string> _searchPatternList = new List<string>(extensions);            
        List<string> fileList = new List<string>();
        foreach (string ext in _searchPatternList)
        {
            foreach (string subFile in Directory.GetFiles(this.tbFolderTo.Text, ext))
            {
                fileList.Add(subFile);
            }
        }

        foreach (string file in fileList)
        {
            this.lbFileNamesTo.Items.Add(file);
        }

but the problem by testing with bogus files like filexp2.xlsq or filexp.xlsa , I see these files in my list box to display the list of found files, in code I limited extensions to xls and xlsx I don't know why i see these files in the result

with the result I do not see any difference between the code I puted and this code

        System.IO.FileInfo[] files = null;
        System.IO.DirectoryInfo dirInfo;

        dirInfo = new System.IO.DirectoryInfo(this.tbFolderTo.Text);
        files = dirInfo.GetFiles("*.xls*");

thanks for help

Siwar
  • 219
  • 2
  • 7
  • 18

4 Answers4

10

From MSDN:

When using the asterisk wildcard character in a searchPattern, such as "*.txt", the matching behavior when the extension is exactly three characters long is different than when the extension is more or less than three characters long. A searchPattern with a file extension of exactly three characters returns files having an extension of three or more characters, where the first three characters match the file extension specified in the searchPattern. A searchPattern with a file extension of one, two, or more than three characters returns only files having extensions of exactly that length that match the file extension specified in the searchPattern. When using the question mark wildcard character, this method returns only files that match the specified file extension. For example, given two files, "file1.txt" and "file1.txtother", in a directory, a search pattern of "file?.txt" returns just the first file, while a search pattern of "file*.txt" returns both files.

http://msdn.microsoft.com/it-it/library/wz42302f.aspx

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
qwertoyo
  • 1,332
  • 2
  • 15
  • 31
0

As @qwertoyo has quite correctly quoted the note from MSDN indicating why you have a problem I thought maybe i'd try to give you another solution.

You could enumerate all the files in a directory, (by using EnumerateFiles in place of GetFiles you dont need to wait for the entire directory) and pull out only those files which match your requirement:

string[] extensions = new[] { ".xls", ".xlsx" };
var excelFiles = Directory.EnumerateFiles(this.tbFolderTo.Text)
                     .Where(f => extensions.Contains(File.GetExtension(f)));

If using .NET 3.5 or earlier, you'll have to fall back to the GetFiles solution, but with a big directory, it will be slow!

string[] extensions = new[] { ".xls", ".xlsx" };
var excelFiles = Directory.GetFiles(this.tbFolderTo.Text)
                     .Where(f => extensions.Contains(Path.GetExtension(f)));
Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • i don't have a method GetExtension in FileInfo i use .NET 3.5 – Siwar Apr 29 '13 at 09:36
  • @Siwar - `GetExtension` is on `File` not `FileInfo` and ive updated for a .NET 3.5 solution – Jamiec Apr 29 '13 at 09:36
  • -i have this error 'System.IO.File' does not contain a definition for 'GetExtension' – Siwar Apr 29 '13 at 10:26
  • @Siwar - My bad. It's [`Path.GetExtension`](http://msdn.microsoft.com/en-us/library/system.io.path.getextension.aspx) - `Path` is also in `System.IO`. – Jamiec Apr 29 '13 at 10:58
  • thanks, i get a solution in this link http://www.codeproject.com/Articles/153471/DirectoryInfo-GetFiles-returns-more-files-than-exp – Siwar Apr 29 '13 at 12:38
0

This code will work if you're using .NET 4.0 and will improves memory usage when compared to GetFiles():

string[] patterns = new { ".xls", ".xlsx" };

return patterns.AsParallel().SelectMany(p => 
    Directory.EnumerateFiles(path, p, SearchOption.AllDirectories));

Sources:

Community
  • 1
  • 1
greg84
  • 7,541
  • 3
  • 36
  • 45
  • I'm pretty sure this will suffer the same problem as the OP already had - see the quoted section from MSDN in qwertoyo answer! – Jamiec Apr 29 '13 at 09:26
  • It shouldn't, because I'm not using the asterisk character. The MSDN quote only applies "When using the asterisk wildcard character..." – greg84 Apr 29 '13 at 09:29
  • i'm using .NET 3.5, i can't use this sollution :( – Siwar Apr 29 '13 at 09:34
0

If you do not want implicit not-exact matching, you can always fall back to WinAPI PathMatchSpec function, which pretty much is used to handle wildcards accross the system, without annoyances like one in Directory.GetFiles (what an inconsistency!)

public static class DirectoryEx
{
    [DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
    private static extern bool PathMatchSpec(string file, string spec);

    public static IEnumerable<string> GetFilesExact(string path, string searchPattern)
    {
        var files = Directory.GetFiles(path, searchPattern).ToList();
        foreach (var file in files)
        {
            if (PathMatchSpec(file, searchPattern))
            {
                yield return file;
            }
        }
    }
}

That way you can still use wildcards, but in a predictable way. So change inner loop to:

foreach (string subFile in DirectoryEx.GetFilesExact(this.tbFolderTo.Text, ext))
{
    fileList.Add(subFile);
}

And you are good to go.

gwiazdorrr
  • 6,181
  • 2
  • 27
  • 36