递归将ZIP文件结构转换为Treeview

时间:2018-10-23 01:24:43

标签: vb.net

我一直想知道是否有递归方式使我的代码在下面的功能中发挥作用。

我确实在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

此代码运行良好,并生成这样的树状视图。我只是希望有人可以阐明可能使用递归来加快速度。 TreeView Image

2 个答案:

答案 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