我一直想知道是否有递归方式使我的代码在下面的功能中发挥作用。
我确实在Stack Overflow上看到了一些示例,但是它们似乎都只处理本地驱动器上的现有文件结构。
Zip文件没有文件结构。仅列出完整路径。
在我没有发布任何编码尝试之前,我不知道该怎么做。递归是巫术魔术,我从来没有能够在没有示例工作的情况下正确地进行编码。
以下是我制定的解决方案。如果有人试图解决这个问题。它可以工作,但只能处理8级嵌套。一旦了解了代码的工作原理,就可以轻松扩展它。
如果可以将其转换为更紧凑且可能更快的内容,我想尝试在一些指导下对其进行编码。
Module modZipFolderResolver
Public root As root_
Public Structure root_
Public node() As root_
Public name As String
Public index As Integer
Public isDir As Boolean
Public count As Integer
Dim n As TreeNode
Public Function find(f As String, ByRef idx As Integer)
If node Is Nothing Then
Return False
End If
For k = 0 To Me.node.Length - 1
If node(k).name = f Then
idx = k
Return True
End If
Next
Return False
End Function
Public Sub add(ByRef s As String, ByRef idx As Integer, ByVal fullname As String, ByRef p_node As TreeNode, ByVal isDir As Boolean)
ReDim Preserve Me.node(Me.count + 1)
idx = Me.count
node(Me.count) = New root_
node(Me.count).name = s
'------------------------------------
'add node
Dim nn As New TreeNode 'create new treevire node
nn.Tag = fullname
nn.Text = Me.node(Me.count).name
If isDir Then ' set image index based on type
Me.node(Me.count).isDir = True
nn.SelectedImageIndex = 2
nn.ImageIndex = 2
nn.Name = "dir" 'used for evauation when clicked
Else
Me.node(Me.count).isDir = False
nn.SelectedImageIndex = 1
nn.ImageIndex = 0
nn.Name = ""
End If
'------------------------------------
' make a new one if its blank
If p_node Is Nothing Then
p_node = New TreeNode
p_node.Text = Me.name
End If
Me.node(Me.count).n = New TreeNode
Me.node(Me.count).n = nn
p_node.Nodes.Add(Me.node(Me.count).n)
'------------------------------------
Me.count += 1
End Sub
End Structure
Public Sub build_tree()
'--------------------------------------------------------
'create the root node
root = New root_
GC.Collect() ' clean up garbage if we just killed existing data
root.n = New TreeNode
root.n.SelectedImageIndex = 2
root.n.ImageIndex = 2
root.n.Text = frmTreeList.tv_filenames.SelectedNode.Text
root.n.Name= "dir"
frmTreeList.tv_contents.Nodes.Add(root.n) 'Add to treeview
'--------------------------------------------------------
'now the fun up part. Create the nested tree structure.
Dim indexes(9) As Integer 'used to keep track of where we are in the tree structure
Dim isDir As Boolean = False ' flag for setting up image index
For Each ent In current_package
Dim ext = Path.GetExtension(ent.FileName)
If ext.Length > 0 Then 'is this entry a file or directory?
isDir = False
Else
isDir = True
End If
Dim a = ent.FileName.Split("/")
For i = 0 To 8 ' 8 levels deep enough?
If a.Length = 2 Then
Exit For
End If
If i > a.Length - 1 Then
Exit For
End If
For k = i To a.Length - 1
If a(k) = "" Then
Exit For
End If
Dim idx As Integer
Select Case k
Case 0
If root.find(a(0), idx) Then
indexes(0) = idx
Else
root.add(a(0), idx, ent.FileName, root.n, isDir)
indexes(0) = idx
Exit For
End If
Case 1
If root.node(indexes(0)).find(a(1), idx) Then
indexes(1) = idx
Else
Dim n = root.node(indexes(0)).n
root.node(indexes(0)).add(a(1), idx, ent.FileName, n, isDir)
indexes(1) = idx
Exit For
End If
Case 2
If root.node(indexes(0)).node(indexes(1)).find(a(2), idx) Then
indexes(2) = idx
Else
Dim n = root.node(indexes(0)).node(indexes(1)).n
root.node(indexes(0)).node(indexes(1)).add(a(2), idx, ent.FileName, n, isDir)
indexes(2) = idx
Exit For
End If
Case 3
If root.node(indexes(0)).node(indexes(1)).node(indexes(2)).find(a(3), idx) Then
indexes(3) = idx
Else
Dim n = root.node(indexes(0)).node(indexes(1)).node(indexes(2)).n
root.node(indexes(0)).node(indexes(1)).node(indexes(2)).add(a(3), idx, ent.FileName, n, isDir)
indexes(3) = idx
Exit For
End If
Case 4
If root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).find(a(4), idx) Then
indexes(4) = idx
Else
Dim n = root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).n
root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).add(a(4), idx, ent.FileName, n, isDir)
indexes(4) = idx
Exit For
End If
Case 5
If root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).find(a(5), idx) Then
indexes(5) = idx
Else
Dim n = root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).n
root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).add(a(5), idx, ent.FileName, n, isDir)
indexes(5) = idx
Exit For
End If
Case 6
If root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).node(indexes(5)).find(a(6), idx) Then
indexes(6) = idx
Else
Dim n = root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).node(indexes(5)).n
root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).node(indexes(5)).add(a(6), idx, ent.FileName, n, isDir)
indexes(6) = idx
Exit For
End If
Case 7
If root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).node(indexes(5)).node(indexes(6)).find(a(7), idx) Then
indexes(7) = idx
Else
Dim n = root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).node(indexes(5)).node(indexes(6)).n
root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).node(indexes(5)).node(indexes(6)).add(a(7), idx, ent.FileName, n, isDir)
indexes(7) = idx
Exit For
End If
Case 8
If root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).node(indexes(5)).node(indexes(6)).node(indexes(7)).find(a(8), idx) Then
indexes(8) = idx
Else
Dim n = root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).node(indexes(5)).node(indexes(6)).node(indexes(7)).n
root.node(indexes(0)).node(indexes(1)).node(indexes(2)).node(indexes(3)).node(indexes(4)).node(indexes(5)).node(indexes(6)).node(indexes(7)).add(a(8), idx, ent.FileName, n, isDir)
indexes(8) = idx
Exit For
End If
End Select
Next 'k
Next 'i
Next 'each ent
End Sub
End Module
答案 0 :(得分:1)
就算法而言,我将按以下方式进行:-
对于每个路径:- 用“ /”字符将路径分成字符串数组。 将此数组连同根节点和索引0一起传递到新函数中,以表明您正在使用该数组。
该功能应:- 获取传入的索引的路径组件 在作为与路径组件匹配的参数传入的节点内查找或创建子节点 如果传入的索引等于路径组件数组-1的长度,则返回找到/创建的子节点 否则,该函数应返回对其自身的调用结果,并传入子节点和在+1中传递的索引
此函数应根据需要创建节点,并返回路径的节点
答案 1 :(得分:0)
我发现了一个解决方案,尽管它似乎稍微慢一些。可能是因为必须通过调用堆栈返回。我将设置一个计时器,并调用旧版本和新版本,然后使用最快的版本。 这不仅限于zip文件。任何文件路径列表都会生成正确构建的TreeView。
新方法的优点是,嵌套深度没有限制,除非扩展代码,否则旧版本限于8。
只是有一个主意。检查路径的拆分数组有多深,如果它的8个以上调用新版本,否则调用旧版本。
更新:我做了一些时间研究,而新版本的运行速度较慢。
不同大小的zip文件的结果
==================================
Path Count: 10756
New method: 0.328ms
Old method: 0.275ms
==================================
Path Count: 11860
New method: 0.338ms
Old method: 0.287ms
==================================
Path Count: 06672
New method: 0.189ms
Old method: 0.177ms
==================================
Path Count: 01168
New method: 0.032ms
Old method: 0.027ms
新方法代码:
Public Sub build_tree_recrusive()
'--------------------------------------------------------
'create the root node
root = New root_
GC.Collect() ' clean up garbage if we just killed existing data
root.n = New TreeNode
root.n.SelectedImageIndex = 2
root.n.ImageIndex = 2
root.n.Text = frmTreeList.tv_filenames.SelectedNode.Text
root.n.Name = "dir"
frmTreeList.tv_contents.Nodes.Add(root.n) 'Add to treeview
'--------------------------------------------------------
'now the fun up part. Create the nested tree structure.
Dim indexes(9) As Integer 'used to keep track of where we are in the tree structure
Dim isDir As Boolean = False ' flag for setting up image index
For Each ent In current_package
Dim ext = Path.GetExtension(ent.FileName)
If ext.Length > 0 Then 'is this entry a file or directory?
isDir = False
Else
isDir = True
End If
Dim a = ent.FileName.Split("/")
rc(a, 0, 0, root, ent.FileName, isDir)
Next 'each ent
End Sub
Private Function rc(ByRef a() As String, ByRef idx As Integer, ByRef ndx As Integer, ByRef node As root_, ByRef fullpath As String, ByVal isDir As Boolean) As Boolean
If idx = a.Length Then Return True
If a(idx) = "" Then Return True
If node.find(a(idx), ndx) Then
If rc(a, idx + 1, ndx, node.node(ndx), fullpath, isDir) Then
Return True
End If
Else
node.add(a(idx), ndx, fullpath, node.n, isDir)
If rc(a, idx + 1, ndx, node.node(ndx), fullpath, isDir) Then
Return True
End If
End If
Return True
End Function