题
System.IO.Directory.GetFiles()
返回一个 string[]
. 。返回值的默认排序顺序是什么?我是按名字假设的,但如果是的话,当前的文化对其影响有多大?您可以将其更改为创建日期之类的内容吗?
更新: MSDN 指出,.Net 3.5 不保证排序顺序,但该页面的 2.0 版本根本没有说明任何内容,并且两个页面都不会帮助您按创建或修改时间等内容进行排序。一旦您拥有数组(它仅包含字符串),该信息就会丢失。我可以构建一个比较器来检查它获取的每个文件,但这意味着在 .GetFiles() 方法可能已经执行此操作时重复访问文件系统。看起来效率很低。
解决方案
如果您对文件的属性(例如 CreationTime)感兴趣,那么使用 System.IO.DirectoryInfo.GetFileSystemInfos() 会更有意义。然后,您可以使用 System.Linq 中的扩展方法之一对它们进行排序,例如:
DirectoryInfo di = new DirectoryInfo("C:\\");
FileSystemInfo[] files = di.GetFileSystemInfos();
var orderedFiles = files.OrderBy(f => f.CreationTime);
编辑 - 抱歉,我没有注意到 .NET2.0 标记,因此忽略 LINQ 排序。不过,使用 System.IO.DirectoryInfo.GetFileSystemInfos() 的建议仍然有效。
其他提示
在 .NET 2.0 中,您需要使用 Array.Sort 对 FileSystemInfos 进行排序。
此外,您可以使用 Comparer 委托来避免仅为比较而声明一个类:
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);
});
这是我使用过的 VB.Net 解决方案。
首先创建一个类来比较日期:
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
然后在对数组进行排序时使用比较器:
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)
Dim Files() As String
Files = System.IO.Directory.GetFiles("C:\")
Array.Sort(Files)
你是对的,默认是我的名字asc。我发现更改排序顺序的唯一方法是从 FileInfo 集合创建数据表。
然后,您可以使用数据表中的 DefaultView 并使用 .Sort 方法对目录进行排序。
这是相当复杂且相当缓慢的,但我希望有人会发布更好的解决方案。
您可以实现自定义 iComparer 来进行排序。读取文件的文件信息并根据需要进行比较。
IComparer comparer = new YourCustomComparer();
Array.Sort(System.IO.Directory.GetFiles(), comparer);
更简洁的 VB.Net 版本...非常好。谢谢。要以相反的顺序遍历列表,请添加reverse方法...
For Each fi As IO.FileInfo In filePaths.reverse
' Do whatever you wish here
Next
这 MSDN 文档 声明不保证返回值的任何顺序。您必须使用 Sort() 方法。
您可以编写自定义 IComparer 接口来按创建日期排序,然后将其传递给 Array.Sort。您可能还想查看 StrCmpLogical,它用于执行 Explorer 使用的排序(将数字与文本正确排序)。
如果您想按创建日期之类的内容进行排序,您可能需要使用 DirectoryInfo.GetFiles,然后使用合适的谓词对结果数组进行排序。
只是一个想法。我喜欢找到一种简单的方法并尝试重新使用现有的资源。如果我要对文件进行排序,我只需创建一个进程并将 syscal 设置为“DIR [x:\Folders\SubFolders*.*] /s /b /on”并捕获输出。
使用系统的 DIR 命令,您可以按以下方式排序:
/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
我不确定 D = 按日期/时间是否使用 LastModifiedDate 或 FileCreateDate。但是如果所需的排序顺序已经内置在 DIR 命令中,我将通过调用 syscall 来获取它。而且速度很快。我只是个懒人;)
经过一番谷歌搜索后,我发现可以按特定日期/时间进行排序:-
/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
更简洁的 VB.Net 版本,如果有人感兴趣的话
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