2008-09-09 33 views
58

System.IO.Directory.GetFiles() devuelve un string[]. ¿Cuál es el orden de clasificación predeterminado para los valores devueltos? Asumo por su nombre, pero si es así, ¿cuánto lo afecta la cultura actual? ¿Puedes cambiarlo a algo así como la fecha de creación?Ordenando Directory.GetFiles()

Actualización: MSDN señala que el orden de clasificación no está garantizado para .Net 3.5, pero la versión 2.0 de la página no dice nada y ninguna de las páginas lo ayudará a ordenar cosas como creación o modificación hora. Esa información se pierde una vez que tiene la matriz (contiene solo cadenas). Podría construir un comparador que compruebe cada archivo que obtiene, pero eso significa acceder al sistema de archivos repetidamente cuando presumiblemente el método .GetFiles() ya lo hace. Parece muy ineficiente.

Respuesta

103

Si usted está interesado en propiedades de los archivos tales como CreationTime, entonces tendría más sentido utilizar System.IO.DirectoryInfo.GetFileSystemInfos(). A continuación puede ordenar estas usando uno de los métodos de extensión en System.Linq, por ejemplo .:

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

Editar - lo siento, no me di cuenta la etiqueta .NET2.0 así que ignora la clasificación LINQ. La sugerencia de utilizar System.IO.DirectoryInfo.GetFileSystemInfos() aún se mantiene.

+0

No hay LINQ en .Net2.0, pero sigue siendo la mejor respuesta hasta el momento. –

+0

Tuve que dejar de aceptar la respuesta, porque cuando volví hoy para implementarlo, el método .Net 2.0 se llama .GetFileSystemEntries, y _it solo devuelve una matriz de cadenas._ –

+3

Joel, estás buscando el objeto equivocado. System.IO.Directory tiene el método GetFileSystemEntries. Mi sugerencia fue utilizar System.IO.DirectoryInfo, que tiene el método GetFileSystemInfos. Espero que esto ayude. –

7

Dim Files() As String 
Files = System.IO.Directory.GetFiles("C:\") 
Array.Sort(Files) 
5

De msdn:

El orden de los nombres de los archivos devueltos no está garantizada; use el método Sort() si se requiere un orden de clasificación específico.

El método Sort() es el Array.Sort estándar(), que toma en IComparables (entre otras sobrecargas), por lo que si se ordena por fecha de creación, que se encargará de localización basado en la configuración del equipo.

2

El MSDN Documentation indica que no hay garantía de ningún orden en los valores devueltos. Tienes que usar el método Sort().

2

Tiene la razón, el valor predeterminado es mi nombre asc. La única forma que he encontrado para cambiar el orden de clasificación es crear una tabla de datos de la colección FileInfo.

A continuación, puede utilizar el DefaultView de la tabla de datos y ordenar el directorio con el método .Sort.

Esto es bastante complicado y bastante lento, pero espero que alguien publique una mejor solución.

+3

El valor por defecto es el fin del sistema de archivos en los devuelve. Si está utilizando NTFS, serán ordenados alfa, pero si usando FAT32, se devolverán en orden de tabla (es decir, más o menos el orden de creación). –

2

Puede escribir una interfaz IComparer personalizada para ordenar por fecha de creación y luego pasarla a Array.Sort. Probablemente también quiera ver StrCmpLogical, que es lo que se usa para hacer la clasificación que usa Explorer (ordenando los números correctamente con el texto).

2

Si desea ordenar por fecha de creación, probablemente necesite utilizar DirectoryInfo.GetFiles y luego ordenar la matriz resultante utilizando un predicado adecuado.

3

Puede implementar iComparer personalizado para hacer la clasificación. Lea la información del archivo de los archivos y compárelo como desee.

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

msdn info IComparer interface

12

Aquí está la solución VB.Net que he usado.

En primer lugar hacer una clase para comparar fechas:

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 

a continuación, utilizar el comparador de clasificación, mientras que la matriz:

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

He editado el código de muestra porque Array .Sort necesita una instancia del DateComparer, o aparece el mensaje "DateComparer es un tipo y no se puede usar como una expresión". Gracias por el código, ya que estaba casi listo para usar. – AlfonsoML

12

En .NET 2.0, tendrá que utilizar a Array.Sort ordenar el FileSystemInfos.

Además, puede utilizar un delegado Comparer para no tener que declarar una clase sólo para la comparación:

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); 
            }); 
+1

Hola Chris, ¿el comentario en el código es incorrecto? ¿Establece ordenar por tiempo de creación, pero LastWriteTime no se utiliza CreationTime? ¡Solo me di cuenta cómo después de la cara este comentario es! – AidanO

1

Es sólo una idea. Me gusta encontrar una salida fácil y tratar de reutilizar los recursos ya disponibles. si tuviera que ordenar archivos, solo habría creado un proceso y haría syscal a "DIR [x: \ Folders \ SubFolders *. *]/s/b/on" y capturaría el resultado.

Con DIR del sistema de mando se puede ordenar por:

/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 

Yo no estoy seguro si D = Por Fecha/Hora está utilizando LastModifiedDate o FileCreateDate. Pero si el orden de clasificación necesario ya está incorporado en el comando DIR, lo obtendré llamando a syscall. Y es RÁPIDO. Soy apenas el individuo perezoso;)

Después de un poco de googling encontré interruptor especial para ordenar por fecha/hora: -

/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 
1

Una versión más sucinta VB.Net, si alguien está interesado

Dim filePaths As Linq.IOrderedEnumerable(Of IO.FileInfo) = _ 
    New DirectoryInfo("c:\temp").GetFiles() _ 
    .OrderBy(Function(f As FileInfo) f.CreationTime) 
For Each fi As IO.FileInfo In filePaths 
    ' Do whatever you wish here 
Next 
3

Una versión más sucinta de VB.Net ... es muy agradable. Gracias. para recorrer la lista en orden inverso, añadir el método de ósmosis ...

For Each fi As IO.FileInfo In filePaths.reverse 
    ' Do whatever you wish here 
Next