Vb.net 已排序目录列表中的已排序文件列表
我有这样的目录/文件结构:Vb.net 已排序目录列表中的已排序文件列表,vb.net,Vb.net,我有这样的目录/文件结构: myPath\20140511\0002.xml \0003.xml \20140513\0004.xml \0006.xml \0008.xml \20140515\0009.xml \20140516\0010.xml \0011.xml \0012.xml 。。。其中myPat
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格式的日期命名的目录
如何从中获得排序目录列表和排序文件列表?
例如,如果我需要2014年5月12日的文件。至2014年5月15日。应列出文件0004.xml、0006.xml、0008.xml、0009.xml。请注意,缺少一些文件,也缺少一些日期。
目录应按字母顺序读取
如何做到这一点?简单明了:
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
您的日期已经是yyyyMMdd格式,基本上是整数:易于排序->使用SortedListOf Int32,任何内容
我假设您的文件系统结构是不可变的:您总是有一个日期文件夹名称的有序列表,每个日期都有一个文件名列表。
免责声明:太长,无法在IDE中测试。。可能包含打字错误或不起作用的东西,我将在以后的某个时候尝试修复
快点。。
尤其是当我不确定是否允许我安全地访问.key时
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(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
这是一个过载:
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
下面是基本功能:
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
公共声明与目录的声明几乎相同,但调用GetFileRangeDateStart、DateEnd
然后你可以写:
Try
Dim MyListOfDir As List(Of String) = _
New CustomDateTypeDirectory(myPath)().GetDirectoryRange( _
DateStart, DateEnd, True, False)
' ....
' ....
您可以将Try替换为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
对GetFileRangeDateStart、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
782年11月25日
提示:虽然这可能不是最优雅的方式,但它很容易实现。您可以将文件信息读入ADO.NET数据表。在填充DataTable时,可以使用父级的日期填充缺少的日期。使用ADO排序、筛选功能获取所需内容。有些代码已经在这里了:。好的。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
我之所以不喜欢Linq,是因为调试代码的难度比这复杂得多
另一个答案来自我的一个AddonManager,它处理数千个zip文件和目录作为游戏的资源。我的文件夹方案类型为:
yyyyMMdd\*.*
yyyyMMdd_Saturday\*.*
yyyyMMdd_Monday_ToDo_Series\*.*
并且可以包含以下子目录:
\_Installed
\_Rejected
\_Revised
对于性能问题,Int32是我的最佳选择,每个用户操作数千次查询,以及绘制GDI+或解压缩zip文件等其他令人眼花缭乱的事情,但是Karl,您的场景非常复杂。请注意,我的目录和文件名已经可以作为字符串进行排序。这里应该有更简单的解决方案。无论如何,感谢您提供值得研究的示例。堆栈溢出不是一种代码编写服务。如果您向我们展示您尝试过的代码并解释为什么它不起作用,我们可以帮助您。谁说堆栈溢出是代码编写服务?我的代码可能会将可能的解决方案转向错误的方向,所以有时候最好从独立的角度来看待常见的问题,比如我的问题。看来你在投反对票之前想得不够。嗯,也很复杂。您是否建议我使用DirectoryInfo.GetFiles来排列dirInfo+fileinfo,并使用相关的IComparer对其进行排序。不是很快,但我想编码更少?无论如何,你的例子很有教育意义,所以我会接受你的答案。谢谢。@user973238-如果1和2的类型相同,则可以使用Anything1+Anything2的数组。DirInfo和FileInfo的类型不同。您可以使用字符串路径,但您完成了一项特定任务:选择一组提供开始日期和结束日期的目录和/或文件。排序非常简单,而且你的数组会做得很好;然后,考虑代码以获取范围内的文件。。您将得到与上面的Linq示例一样多的行:@user973238-关键部分不是对集合进行排序。每个排序通常是InRangeDir与Linq的一行代码顺序;字符串的排序。。。;数组.排序。。关键部分是选择范围内的项目。该任务使代码变长。。。如果按子目录yyyyMMdd\xxxx.xml排序,将失去提取yyyyMMdd的能力,因此必须编写更多代码来提取该文件。这就是为什么最好将目录解析与使用键的直接项访问(例如在变量或类中)结合起来。另一个答案这个答案只是绕过所有的tha
t、 @user973238-谢谢你的投票和接受:复杂是品味的问题。如果有这样的东西就太好了:Dim Files As String=Array.JoinDirectory.selectinginmypath Where DateStart*我不知道。这里涉及ADO似乎“有点过于复杂”。
yyyyMMdd\*.*
yyyyMMdd_Saturday\*.*
yyyyMMdd_Monday_ToDo_Series\*.*
\_Installed
\_Rejected
\_Revised