tags:

views:

9436

answers:

11

System.IO.Directory.GetFiles() returns a string[]. What is the default sort order for the returned values? I'm assuming by name, but if so how much does the current culture effect it? Can you change it to something like creation date?

Update: MSDN points out that the sort order is not guaranteed for .Net 3.5, but the 2.0 version of the page doesn't say anything at all and neither page will help you sort by things like creation or modification time. That information is lost once you have the array (it contains only strings). I could build a comparer that would check for each file it gets, but that means accessing the file system repeatedly when presumably the .GetFiles() method already does this. Seems very inefficient.

+1  A: 
        Dim Files() As String
        Files = System.IO.Directory.GetFiles("C:\")
        Array.Sort(Files)
Kibbee
+3  A: 

From msdn:

The order of the returned file names is not guaranteed; use the Sort() method if a specific sort order is required.

The Sort() method is the standard Array.Sort(), which takes in IComparables (among other overloads), so if you sort by creation date, it will handle localization based on the machine settings.

Guy Starbuck
A: 

The MSDN Documentation states that there is no guarantee of any order on the return values. You have to use the Sort() method.

Vaibhav
A: 

You are correct, the default is my name asc. The only way I have found to change the sort order it to create a datatable from the FileInfo collection.

You can then used the DefaultView from the datatable and sort the directory with the .Sort method.

This is quite involve and fairly slow but I'm hoping someone will post a better solution.

GateKiller
The default is the order the file system returns them in. If you're using NTFS, they will be alpha sorted, but if you're using FAT32, they will be returned in table order (i.e., more or less order of creation).
Brad Wilson
A: 

You could write a custom IComparer interface to sort by creation date, and then pass it to Array.Sort. You probably also want to look at StrCmpLogical, which is what is used to do the sorting Explorer uses (sorting numbers correctly with text).

Tina Marie
A: 

If you want to sort by something like creation date you probably need to use DirectoryInfo.GetFiles and then sort the resulting array using a suitable Predicate.

samjudson
A: 

You can implement custom iComparer to do sorting. Read the file info for files and compare as you like.

IComparer comparer = new YourCustomComparer();
Array.Sort(System.IO.Directory.GetFiles(), comparer);

msdn info IComparer interface

Vertigo
+15  A: 

If you're interested in properties of the files such as CreationTime, then it would make more sense to use System.IO.DirectoryInfo.GetFileSystemInfos(). You can then then sort these using one of the extension methods in System.Linq, e.g.:

DirectoryInfo di = new DirectoryInfo("C:\\");
FileSystemInfo[] files = di.GetFileSystemInfos();
var orderedFiles = files.OrderBy(f => f.CreationTime);

Edit - sorry, I didn't notice the .NET2.0 tag so ignore the LINQ sorting. The suggestion to use System.IO.DirectoryInfo.GetFileSystemInfos() still holds though.

Ian Nelson
No LINQ in .Net2.0, but the still the best answer so far.
Joel Coehoorn
I had to unaccept the answer, because when I went back today to implement it the .Net 2.0 method is called .GetFileSystemEntries, and _it still only returns a string array._
Joel Coehoorn
Joel, you're looking on the wrong object. System.IO.Directory has the GetFileSystemEntries method.My suggestion was to instead use System.IO.DirectoryInfo, which has the GetFileSystemInfos method.Hope this helps.
Ian Nelson
Okay, I see the distinction now. Thanks.
Joel Coehoorn
Technically, you can do LINQ-to-Objects in .NET 2, which is all you'd need for this sort of sorting. http://www.albahari.com/nutshell/linqbridge.aspx
Joel Mueller
+3  A: 

Here's the VB.Net solution that I've used.

First make a class to compare dates:

Private Class DateComparer
 Implements System.Collections.IComparer

 Public Function Compare(ByVal info1 As Object, ByVal info2 As Object) As Integer Implements System.Collections.IComparer.Compare
  Dim FileInfo1 As System.IO.FileInfo = DirectCast(info1, System.IO.FileInfo)
  Dim FileInfo2 As System.IO.FileInfo = DirectCast(info2, System.IO.FileInfo)

  Dim Date1 As DateTime = FileInfo1.CreationTime
  Dim Date2 As DateTime = FileInfo2.CreationTime

  If Date1 > Date2 Then Return 1
  If Date1 < Date2 Then Return -1
  Return 0
 End Function
End Class

Then use the comparer while sorting the array:

Dim DirectoryInfo As New System.IO.DirectoryInfo("C:\")
Dim Files() As System.IO.FileInfo = DirectoryInfo.GetFiles()
Array.Sort(Files, DateComparer)
sebastiaan
+1  A: 

In .NET 2.0, you'll need to use Array.Sort to sort the FileSystemInfos.

Additionally, you can use a Comparer delegate to avoid having to declare a class just for the comparison:

DirectoryInfo dir = new DirectoryInfo(path);
FileSystemInfo[] files = dir.GetFileSystemInfos();

// sort them by creation time
Array.Sort<FileSystemInfo>(files, delegate(FileSystemInfo a, FileSystemInfo b)
                                    {
                                        return a.LastWriteTime.CompareTo(b.LastWriteTime);
                                    });
Chris Karcher
A: 

Just an idea. I like to find an easy way out and try re use already available resources. if I were to sort files I would've just create a process and make syscal to "DIR [x:\Folders\SubFolders*.*] /s /b /on" and capture the output.

With system's DIR command you can sort by :

/O          List by files in sorted order.
sortorder    N  By name (alphabetic)       S  By size (smallest first)
             E  By extension (alphabetic)  D  By date/time (oldest first)
             G  Group directories first    -  Prefix to reverse order

The /S switch includes sub folders

I AM NOT SURE IF D = By Date/Time is using LastModifiedDate or FileCreateDate. But if the needed sort order is already built-in in the DIR command, I will get that by calling syscall. And it's FAST. I am just the lazy guy ;)

After a little googling I found switch to sort by particular date/time:-

/t [[:]TimeField] : Specifies which time field to display or use for sorting. The following list describes each of the values you can use for TimeField. 

Value Description 
c : Creation
a : Last access
w : Last written
Mehdi Anis