首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >递归地将ZIP文件结构转换为treeview

递归地将ZIP文件结构转换为treeview
EN

Stack Overflow用户
提问于 2018-10-23 09:24:43
回答 2查看 334关注 0票数 2

我一直在想,有没有办法让我下面的代码以递归的方式运行。

我在Stack Overflow上确实看过一些示例,但它们似乎都只处理本地驱动器上的现有文件结构。

Zip文件没有文件结构。仅完整路径列表。

在我因为没有发布任何编写代码的尝试而受到抨击之前,我不知道该怎么做。递归是巫术,我从来没有能够正确地编码没有示例工作。

下面是我想出的一个解决方案。如果有人一直在试图解决这个问题..尝尝这个。它可以工作,但只能处理8层嵌套。一旦你理解了代码是如何工作的,它就可以很容易地扩展。

如果可以将其转换为更紧凑、可能更快的代码,我会尝试使用一些指导对其进行编码。

代码语言:javascript
复制
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。我只是希望有人能解释一下,也许可以使用递归来加快速度。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-23 19:31:57

就算法而言,我会这样做:

对于每个路径:-使用"/“字符将路径拆分为字符串数组。将这个数组连同根节点和索引0一起传递到一个新函数中,以表明这就是您要做的事情。

该函数应:-获取传入索引的路径组件查找或创建节点内的子节点,如果传入的索引等于路径组件数组的长度,则在该节点内创建与路径组件匹配的子节点,然后返回找到/创建的子节点,否则该函数应返回调用自身的结果,传入子节点和传入的索引+1

此函数应根据需要创建节点并返回路径的Node

票数 1
EN

Stack Overflow用户

发布于 2018-10-23 22:53:24

我找到了一个解决方案,尽管它似乎只是稍微慢了一点。可能是因为必须通过调用堆栈返回。我将设置一个计时器,并调用旧版本和新版本,我将使用最快的版本。这并不局限于zip文件。任何文件路径列表都将生成正确构建的TreeView。

新方法的优点是,没有嵌套深度的限制,旧版本限制为8,除非扩展代码。

我有个想法..。检查路径的拆分数组有多深,如果超过8就调用新版本,否则调用旧版本。

更新:我做了一些时间研究,新版本速度更慢。

不同大小的zip文件的结果

代码语言:javascript
复制
==================================
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

新的方法代码:

代码语言:javascript
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52939821

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档