tags:

views:

4453

answers:

5

I have the following code

DirectoryInfo taskDirectory = new DirectoryInfo(this.taskDirectoryPath);
FileInfo[] taskFiles = taskDirectory.GetFiles("*" + blah + "*.xml");

I would like to sort the list by filename.

How is this done, as quickly and easily as possible using .net v2.

Thank you

A: 
Comparison<FileInfo> comparison = new Comparison<FileInfo>(delegate(FileInfo a, FileInfo b)
{
    return String.Compare(a.Name, b.Name);
});

Array.Sort(taskFiles, comparison);

But anyway I think the result of GetFiles is already sorted by name...

Thomas Levesque
"But anyway I think the result of GetFiles is already sorted by name..." - from MSDN: The order of the returned file names is not guaranteed
Marc Gravell
GetFiles return files sorted by name only on NTFS drives, because NTFS stores names as binary tree! This is not valid for FAT or any other file system. So you must always use sort to be sure that output is sorted.
arbiter
@Marc : good point !@arbiter : thanks for the explanation
Thomas Levesque
+11  A: 

Call Array.Sort, passing in a comparison delegate:

Array.Sort(taskFiles, delegate(FileInfo f1, FileInfo f2) {
    return f1.Name.CompareTo(f2.Name);
});

In C# 3 this becomes slightly simpler:

Array.Sort(taskFiles, (f1, f2) => f1.Name.CompareTo(f2.Name));

Or you can use a StringComparer if you want to use a case-insensitive sort order:

Array.Sort(taskFiles,
           (x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.Name, y.Name));

(or use string.Compare(x.Name, y.Name, true), or any of the many other ways of comparing strings :)

Jon Skeet
Speaking of C# 3.0, the OrderBy method is even simpler...
Thomas Levesque
@Thomas - but that doesn't do an in-place sort, which is (I believe) what the OP wants
Marc Gravell
I would only add that is possible to use vs2008 to target 2.0 using c# 3.0 syntax ;)
kentaromiura
@kentaromiura : yes, but there isn't only syntax involved here... the System.Core assembly is necessary as well, and isn't available in .NET 2.0. However it should be possible to make it work in 2.0 using LinqBridge (http://code.google.com/p/linqbridge/)
Thomas Levesque
+3  A: 
Array.Sort(taskFiles, delegate (FileInfo x, FileInfo y) {
    return string.Compare(x.Name,y.Name);
});
Marc Gravell
A: 

http://mattandchristy.com/post/2008/02/Custom-Sorting-In-C-Sharp.aspx

It looks like the default sort is by filename, have you tested that? Anyway the example I linked to is similar to the other suggestions here, just a little more documentation to it :o)

noesgard
from MSDN: The order of the returned file names is not guaranteed
Marc Gravell
A: 
    public class FileComparer : IComparer
        {
         public enum CompareBy
         {
          Name /* a-z */,
          LastWriteTime /* oldest to newest */,
          CreationTime  /* oldest to newest */,
          LastAccessTime /* oldest to newest */,
          FileSize /* smallest first */,

         }
         // default comparison
         int _CompareBy = (int)CompareBy.Name;
         public FileComparer()
         {
         }

         public FileComparer(CompareBy compareBy)
         {
          _CompareBy = (int)compareBy;
         }
         int IComparer.Compare( object x, object y )
         {
          int output = 0;
          DirectoryInfo file1 = new DirectoryInfo(x.ToString());
          DirectoryInfo file2 = new DirectoryInfo(y.ToString());
          switch(_CompareBy)
          {
           case (int)CompareBy.LastWriteTime:
            output = DateTime.Compare(file1.LastWriteTime, file2.LastWriteTime);
            break;
           case (int)CompareBy.CreationTime:
            output = DateTime.Compare(file1.CreationTime, file2.CreationTime);
            break;
           case (int)CompareBy.LastAccessTime:
            output = DateTime.Compare(file1.LastAccessTime, file2.LastAccessTime);
            break;
    //     case (int)CompareBy.FileSize:
    //      output = Convert.ToInt32(file1.Length - file2.Length);
    //      break;
           case (int)CompareBy.Name:
           default:
            output = (new CaseInsensitiveComparer()).Compare( file1.Name, file2.Name );
            break;
          }
          return output;
         }
        }

///////////////////////////////////
ArrayList list=new ArrayList();   
      string folder = @"D:\DVRData\ICICI\Transaction\21-Dec-08\08_51_23_2231";
      string[] files = Directory.GetFiles(folder);   
      IComparer comp = new FileComparer(FileComparer.CompareBy.CreationTime);
      Array.Sort(files, comp);
      foreach(string file in files)
      {
       list.Add(file);
      }
RV
There's an awful lot of branching going on inside each compare operation, why not just instantiate a single, specialized comparer for each type of sorting instead?
Cecil Has a Name