我有这样的目录/文件结构:
myPath\20140511\0002.xml
\0003.xml
\20140513\0004.xml
\0006.xml
\0008.xml
\20140515\0009.xml
\20140516\0010.xml
\0011.xml
\0012.xml
...其中myPath是数据的基本目录,然后是" yyyyMMdd"中日期命名的目录。格式。
我如何获得带有排序文件列表的排序目录列表?
例如,如果我需要12.05.2014的文件。到2014年5月15日。应列出文件0004.xml,0006.xml,0008.xml,0009.xml。请注意,缺少一些文件,也缺少一些日期
目录应按字母顺序阅读。
如何获得?
答案 0 :(得分:1)
简单明了:
yyyyMMdd
格式,基本上是整数:易于排序 - >使用SortedList
(Of Int32, Anything )免责声明:在IDE中测试它的时间太长了...可能包含错别字或者不能处理以后我会尝试修复的东西(有点像 快点..) 特别是当我不确定是否允许我安全地访问 .Keys 时 SortedList的属性(记住一个例外,例如“IList改变了 访问集合......“)
我会创建一个类(虽然你也可以不用)
Imports System.IO
Private Class CustomDateTypeDirectory
Private p_BaseDirectory As String = ""
Private p_FileSystem As SortedList(Of Int32, List(Of String)) = Nothing
Public Sub New(ByVal NewDirectoryPath As String)
' where NewDirectory stands for myPath
If Directory.Exists(NewDirectoryPath) Then
p_FileSystem = New SortedList(Of Int32, List(Of String))
ParseDirectory(NewDirectoryPath) ' -> below...
Else
' ... Throw New Exception()
End If
End Sub
' Called by New() -> Parse your myPath Directory SubFolders
Private Sub ParseDirectory(ByVal NewDirectoryPath As String)
Dim AllDirectories As String() = Directory.GetDirectories(NewDirecoryPath)
Dim SubDirName As Int32 = -1
p_FileSystem.Clear()
For Each SubDir As String In AllDirectories
SubDirName = IsDateFolder(Path.GetDirectoryName(SubDir))
If SubDirName > -1 Then
p_FileSystem.Add(SubDirName, GetFilesOf(SubDir))
End If
Next
End Sub
' Called by ParseDirectory() -> Validate a SubDir Name as expression of Date
Private Function IsDateFolder(ByVal DirName As String) As Int32
' Here you'll define how you'll consider the name as a valid "yyyyMMdd"
If DirName.Length = 8 Then
Dim IntValidator As Int32 = -1
If Integer.TryParse(DirName, IntValidator) Then
' You could do more checks like if IntValidator > 20000101...
' Or simply try parsing the represented Date...
' I sometimes use "20140300" dit names when I don't know the day,
' so while using Date would throw an exception,
' my function just simply don't care using Integers...
Return IntValidator
Else
Return -1
End If
Else
Return -1
End If
End Function
' Called by ParseDirectory() -> Gather Files of Date SubFolder
Private Function GetFilesOf(ByVal DirPath As String) As List(Of String)
' I'm assuming you make sure to properly sort the Files
Dim AllFiles As String() = Directory.GetFiles(DirPath)
Dim FilesList As New List(Of String)
For Each CurrentFile As String In AllFiles
' Use condition validation if your subDir can contain other files..
FilesList.Add(Path.GetFileName(CurrentFile))
Next
Return FilesList
End Function
End Class
然后创建一些函数以使用您的类
这是基本声明:
Private Function GetDirectoryRange( _
ByVal DateStart As Int32, _
ByVal DateEnd As Int32) As List(Of String)
' ...
End Function
这是一个过载:
Public Function GetDirectoryRange( _
ByVal DateStart As Int32, _
ByVal DateEnd As Int32, _
ByVal IncludeStartingDate As Boolean, _
ByVal IncludeEndingDate As Boolean) As List(Of String)
' ...
End Function
请注意,基本声明为私有,而其他声明为公开。
需要另外两个私人功能:
Private Function GetNearestStartingDate(ByVal DateStart As Int32) As Int32
If p_FileSystem.Count > 0 Then
If p_FileSystem.ContainKey(DateStart) Then
Return DateStart
Else
' Find next available Date...
If p_FileSystem.Keys.Item(0) > DateStart Then
Return p_FileSystem.Keys.Item(0)
ElseIf p_FileSystem.Keys.Item(p_FileSystem.Keys.Count - 1) < DateStart Then
Return - 1 ' DateStart greater than last folder..
Else
' Okay -_- ! Let's find an existing starting Date...
' Simpliest way is iterating the integers
' until it's greater than DateStart
Dim i As Int32 = 1 ' we've already checked for i = 0
While DateStart > p_FileSystem.Keys.Item(i)
i += 1
End While
Return p_FileSystem.Keys.Item(i)
End If
End If
Else
Return -1 ' No StartingDate
End If
End Function
我假设您能够创建另一个GetNearestEndingDate()
函数..(查看您的声誉得分)
不知道为什么上面的基本声明是私有的?因为它仅在中使用有效的DateStart和DateEnd输入。
这是公开声明:
Public Function GetDirectoryRange(DateStart, DateEnd, IncludeStartingDate, IncludeEndingDate) As List(Of String)
' First, fix some possible issues :
If DateStart > DateEnd Then
Dim TempDate As Int32 = DateStart
DateStart = DateEnd
DateEnd = TempDate
End If ' obvious
If Not IncludeStartingDate Then DateStart = DateStart + 1
If Not IncludeEndingDate Then DateEnd = DateEnd - 1
' Now let's find actual values of DateStart and DateEnd...
If DateStart <= DateEnd Then ' Okay, let's look for available dates...
DateStart = GetNearestStartingDate(DateStart)
If DateStart > -1 Then
DateEnd = GetNearestEndingDate(DateEnd)
If DateEnd >= DateStart Then
Return GetDirectoryRange(DateStart, DateEnd)
Else
Return Nothing ' Or Return New List(Of String) - empty !
End If
Else
Return Nothing
End If
Else
Return Nothing
End If
End Function
然后这是基本功能:
Private Function GetDirectoryRange(DateStart, DateEnd) As List(Of String)
Dim NewList As New List(Of String)
Dim DateIndex As Int32 = p_FileSystem.IndexOfKey(DateStart) + 1
NewList.Add(p_BaseDirectory + "\" + DateStart.ToString())
While p_FileSystem.Keys.Item(DateIndex) <= DateEnd
NewList.Add( _
p_BaseDirectory + "\" _
+ p_FileSystem.Keys.Item(DateIndex).ToString())
DateIndex = DateIndex + 1
End while
Return NewList ' New List should contain at least one entry.
End Function
获取文件的函数外推非常简单:
Private Function GetFilesRange(DateStart, DateEnd) As List(Of String)
Dim NewList As New List(Of String)
Dim DateIndex As Int32 = p_FileSystem.IndexOfKey(DateStart)
Dim CurrentFilesList As List(Of String)
Do
CurrentFilesList = p_FileSystem.Item(p_FileSystem.Keys.Item(DateIndex))
For Each CurrentFile As String In CurrentFilesList
NewList.Add( _
p_BaseDirectory + "\" _
+ p_FileSystem.Keys.Item(DateIndex).ToString() + "\" _
+ CurrentFile)
' As CurrentFile if FileName without root path.
Next
DateIndex = DateIndex + 1
Until p_FileSystem.Keys.Item(DateIndex) > DateEnd
Return NewList ' New List should contain at least one entry.
End Function
公开声明与目录声明几乎相同,但改为调用GetFilesRange(DateStart,DateEnd)。
然后你可以写:
Try
Dim MyListOfDir As List(Of String) = _
New CustomDateTypeDirectory(myPath)().GetDirectoryRange( _
DateStart, DateEnd, True, False)
' ....
' ....
你可以用
替换Try with If块 Dim MyDir As New CustomDateTypeDirectory(myPath)
Dim MyListOfDir As List(Of String) = _
MyDir.GetDirectoryRange(DateStart, DateEnd, True, False)
If MyListOfDir IsNot Nothing Then
' or If MyListOfDir.Count > 0 ... depending on how the Function returns value
' ...
End If
对GetFilesRange(DateStart, DateEnd, True, False)
....
您还可以使用新参数类型重载公共声明:
Public Function GetFilesRange( _
ByVal DateStart As Date, ByVal DateEnd As Date, Bool1, Bool2) _
As List(Of String)
' Convert Dates to Int32
Dim IntDateStart As Int32 = _
DateStart.Year * 1000 _
+ DateStart.Month * 100 _
+ DateStart.Day
' ...
Return GetFilesRange(IntDateStart, IntDateEnd, Bool1, Bool2)
End Function
Public Function GetFilesRange( _
ByVal DateStart As String, ByVal DateEnd As String, Bool1, Bool2) _
As List(Of String)
' Convert Dates to Int32
Dim IntDateStart As Int32 = IsDateFolder(DateStart)
Dim IntDateEnd As Int32 = IsDateFolder(DateEnd)
If (IntDateStart > -1) AndAlso (IntDateEnd > -1) Then
Return GetFilesRange(IntDateStart, IntDateEnd, Bool1, Bool2)
Else
Return Nothing ' Or Return New List(Of String)()
End If
End Function
当然,上面的所有内容都不适用于日期文件夹 例如,以低于1000年的任何日期命名。即如果你 你的文件夹中有前导零“0”,如“07821125”所示 11月25日,782 ......
答案 1 :(得分:1)
提示:虽然这可能不是最优雅的方式,但实施起来很容易。您可以将文件信息读入ADO.NET DataTable。在填写DataTable时,您可以使用父日期填写缺少的日期。使用ADO排序,过滤功能来获得您想要的。部分代码已在此处:filling-a-grid-with-files-in-a-folder。
答案 2 :(得分:1)
好。 Linq
- 爱好者会对这个非常基本的代码感到满意:)
Imports System.Linq
Imports System.IO
核心功能:
Private Function GetSubDirs( _
ByVal myPath As String, _
ByVal DateStart As String, ByVal DateEnd As String) _
As IEnumerable(Of String)
DateStart = myPath + "\" + DateStart
DateEnd = myPath + "\" + DateEnd
' weird isn't it ? but heh ! it works...
Dim SelectedSubDirs As IEnumerable(Of String) = _
From InRangeDir In Directory.GetDirectories(myPath) Order By InRangeDir
Where (InRangeDir >= DateStart) AndAlso (InRangeDir <= DateEnd)
Return SelectedSubDirs
End Function
Private Function GetSubDirFiles(ByVal CurrentDir As String) _
As IEnumerable(Of String)
' Gets the Files of one Sub Dir sorted in ascending order.
Return From AnyFile In Directory.GetFiles(CurrentDir) Order By AnyFile
End Function
然后你需要打电话:
Public Function GetSubDirsFilesRange( _
ByVal myPath As String, _
ByVal DateStart As String, ByVal DateEnd As String) _
As List(Of String)
' Gets all the Files in a range of Directory Dates.
Dim AllFiles As New List(Of String)()
Dim SelectedSubDirs As IEnumerable(Of String) = _
GetSubDirs(myPath, DateStart, DateEnd)
For Each CurrentDir As String In SelectedSubDirs
AllFiles.AddRange(GetSubDirFiles(CurrentDir))
Next
Return AllFiles
End Function
Public Function GetSubDirsRange( _
ByVal myPath As String, _
ByVal DateStart As String, ByVal DateEnd As String) _
As List(Of String)
Return GetSubDirs(myPath, DateStart, DateEnd).ToList()
End Function
GetSubDirsFilesRange(myPath, "20140512", "20140515")
' myPath\20140513\0004.xml
' myPath\20140513\0006.xml
' myPath\20140513\0008.xml
' myPath\20140515\0009.xml
为什么我不喜欢Linq
调试比这更复杂的代码的难度。
另一个答案来自我的AddonManager,它处理数千个zip文件和目录作为游戏的资源。我的文件夹方案是类型:
yyyyMMdd\*.*
yyyyMMdd_Saturday\*.*
yyyyMMdd_Monday_ToDo_Series\*.*
并且可以包含以下子目录:
\_Installed
\_Rejected
\_Revised
Int32
是性能问题的最佳选择(每个用户操作数千个查询,以及绘制GDI +或(un)打包zip文件等其他令人眼花缭乱的东西)