Tree (dos/win command) Parser

Stato
Discussione chiusa ad ulteriori risposte.

Whivel

Utente Electrum
11 Luglio 2007
692
2
100
176
TreeParser.vb.txt è la mia soluzione (vb.net)

proprio oggi, è capitato che dovessi farmi un parser, che dato un elenco (su unico file) di cartelle e file, mi doveva rifare tutta la struttura in un controllo treeview....

i comandi ovviamente possibili erano dir (con alcuni parametri) e tree....
alla fine ho optato per tree che sembrava una bella sfida (SEMBRAVA)...

Durante la programmazione, sono passato di quà e mi sono detto.... proponiamolo come esercizio :devil:

Quindi:
bisogna fare un piccolo programma, che preso l'output di tree ("tree PATH /A", "tree PATH /A /F", dove PATH sta ad indicare il percorso assoluto della directory da "ristrutturare" ^^), ricrei la struttura delle directory....
La struttura dovrebbe essere in un controllo treeview, ma siccome non tutti sanno programmare con le interfacce grafiche, il risultato può essere anche un output su console o su file (non barate però ^^)

ho incluso volutamente il parametro /A (ASCII) perchè senza il comando usa dei caratteri particolari che "disegnano" la struttura (linee verticali | orizzontali -, incrociate |-, angoli |_, ecc..)

adesso, per chi non ha windows, un esempio di come è fatto l'output

(vi allego anche i file dell'output - codifica ANSI - così avete tutto il materiale senza equivoci.... perchè la soluzione migliore si basa sulla particolarità dell'output)

tree PATH /A (la cartella è mia, modificata con solo le cose "innocenti" ^^)
Codice:
Elenco del percorso delle cartelle per il volume XXXX
Numero di serie del volume: YYYY-ZZZZ
PATH
+---Browser
|   +---Chrome
|   \---IE
|       \---Plugin
+---Debugging
|   +---altro
|   +---AutoIT
|   +---NET
|   |   \---Reflector
|   |       \---plugin
|   +---Web
|   |   \---plugin
|   \---WIN32
|       +---API
|       \---OllyDBG
+---Messenger
+---Programmazione
|   +---altro
|   +---cpp
|   |   +---Qt4.4.3
|   |   \---wxWidget
|   +---Java
|   +---NET
|   |   +---Aggiornamenti
|   |   \---esempi
|   +---Perl
|   +---Symbian
|   \---VB6
+---Scaricare
+---Software
\---Sounds


tree PATH /A /F
Codice:
Elenco del percorso delle cartelle per il volume XXXX
Numero di serie del volume: YYYY-ZZZZ
PATH
|   install-ia64-minimal-2008.0.iso
|   titanic.mid
|   
+---Browser
|   +---Chrome
|   |       ChromeSetup.exe
|   |       ChromeSetup.zip
|   |       
|   \---IE
|       |   IE7-WindowsXP-x86-ita.exe
|       |   IE8-WindowsVista-x86-ITA.exe
|       |   
|       \---Plugin
|               GoogleToolbarInstaller.exe
|               GoogleToolbarInstaller_download_signed.exe
|               install_flash_player.exe
|               Silverlight.2.0.exe
|               
+---Debugging
|   +---altro
|   |       SandboxieInstall.exe
|   |       UNIVERSALxtract121.rar
|   |       
|   +---AutoIT
|   |       AutoIt_Debugger_Setup_v0.18.0.exe
|   |       myAutToExe2_04_AutoIt3_Decompiler_opensource.zip
|   |       
|   +---NET
|   |   |   DOTNET_Explorer_2008.msi
|   |   |   Remotesoft_DOTNET_Explorer_Evaluation.msi
|   |   |   
|   |   \---Reflector
|   |       |   Reflector.zip
|   |       |   
|   |       \---plugin
|   |               ClassView.zip
|   |               CodeModelViewer.zip
|   |               CodeSearch.zip
|   |               cppcli_a5.zip
|   |               DeblectorAddIn-1.01-Alpha.zip
|   |               Diff.zip
|   |               FileGenerator.zip
|   |               Reflector.FileDisassembler.zip
|   |               reflexil.0.8.bin.zip
|   |               
|   +---Web
|   |   |   Fiddler2BetaSetup.exe
|   |   |   
|   |   \---plugin
|   |           ContentBlocker.zip
|   |           FiddlerRulesTab2Setup.exe
|   |           JsonViewerPackage.zip
|   |           PrettyPrint.alpha.zip
|   |           syntaxview2setup.exe
|   |           TangoXmlViewExtension.zip
|   |           WebViewSetup.exe
|   |           
|   \---WIN32
|       +---API
|       |       APIMonitorTrial.exe
|       |       debugapispy_setup.exe
|       |       spystudio.exe
|       |       
|       \---OllyDBG
|               disasm.zip
|               odbg200h.zip
|               OllySocketTrace_v1.0.zip
|               
+---Messenger
|       amsn-0.97.2-tcl85-windows-installer.exe
|       MsgPlusLive-460.exe
|       Msn_Repair_v2.exe
|       WLinstaller.exe
|       
+---Programmazione
|   |   RegexTester source.zip
|   |   RegexTester.zip
|   |   
|   +---altro
|   |       JanusTrialSetup_2.1.2.msi
|   |       
|   +---cpp
|   |   |   devcpp-4.9.9.2_setup.exe
|   |   |   
|   |   +---Qt4.4.3
|   |   |       eclipse-cpp-ganymede-SR1-win32.zip
|   |   |       qt-eclipse-integration-win32-1.4.3.exe
|   |   |       qt-win-opensource-4.4.3-mingw.exe
|   |   |       
|   |   \---wxWidget
|   |           wxdevcpp_6.10.2_setup.exe
|   |           
|   +---Java
|   |       jcpro450_setup.exe
|   |       jcreatorprov4.50.010keygenhaze.zip
|   |       jdk-6u10-windows-i586-p.exe
|   |       netbeans_mobility.exe
|   |       sun_java_wireless_toolkit-2_5_2-windows.exe
|   |       
|   +---NET
|   |   |   dotnetfx.exe
|   |   |   wx.NET-0.7.2-Windows-Build.zip
|   |   |   
|   |   +---Aggiornamenti
|   |   |       VS80sp1-KB926601-X86-ENU.exe
|   |   |       VS80sp1-KB932232-X86-ENU.exe
|   |   |       VSSDK_PowerToys.msi
|   |   |       
|   |   \---esempi
|   |           Alvas.Audio.zip
|   |           Asprise-OCR-VbNET-Windows_Vista_32bit-4.0.zip
|   |           Asprise-OCR-VbNET-Windows_XP_32bit-4.0.zip
|   |           DS_Play_VB.zip
|   |           DS_Record_VB.zip
|   |           
|   +---Perl
|   |       ActivePerl-5.10.0.1004-MSWin32-x86-287188.msi
|   |       ActivePerl-5.6.1.635-MSWin32-x86.msi
|   |       nmake15.exe
|   |       WWW-Mechanize-1.50.tar.gz
|   |       
|   +---Symbian
|   |       Carbide.c++_v1.3.exe
|   |       Cbdvs3.0.1.exe
|   |       qt-embedded-s60-opensource-src-4.4.2-pyramid.zip
|   |       S60-SDK-200634-3.1-Cpp-f.1090b.zip
|   |       S60_3rd_Ed_Help_VS05.exe
|   |       S60_Platform_Comparison_of_ANSI_Cpp_and_Symbian_Cpp_ v2_0_en.pdf
|   |       
|   \---VB6
|           Asprise-OCR-VB6-Windows_Vista_32bit-4.0.zip
|           
+---Scaricare
|       
+---Software
|       ascgen2-0.9.6-source.7z
|       ascgen2-0.9.6.7z
|       
\---Sounds

la mia soluzione è in vb.net.... ho creato una classe (allegata)... mentre qui posterò tra i tag solo la parte che fa il parsing della stringa contenente l'output di tree..
[ot]
Codice:
    'questa funzione permette di far elaborare un input formato da una sola stringa multilinea (trasformandola in un array di linee)
    Public Function ParseTree(ByVal tree As String) As TreeNode
        Return ParseTree(toLineArray(tree))
    End Function

    'questa funzione fa il parsing dell'array tree, contenente le linee dell'output
    'restituendo i nodi
    Public Function ParseTree(ByVal tree() As String) As TreeNode
        Try
            'contatore dei nodi
            Dim nodes As Integer = 0

            Dim carattere As Char
            Dim nome As Boolean
            Dim str_nome As String

            'il primo nodo della struttura ad albero è la seconda riga (il path)
            Dim FirstNode As New TreeNode(tree(2))
            'gli altri nodi partono dalla terza riga fino alla fine
            For i As Integer = 3 To tree.LongLength - 1
                'siccome è una nuova riga, è un nuovo elemento, di cui
                'non sappiamo ancora il nome, ne a che carattere parte
                nome = False
                str_nome = ""
                'facciamo il parsing di tutta la riga (o quasi ^^)
                For j As Integer = 1 To Len(tree(i))
                    'memorizza in una variabile di appoggio (per non riscrivere tutte le volte mid....)
                    carattere = (Mid(tree(i), j, 1))
                    'se nome=true significa che ho già passato il primo carattere del nome
                    'della cartella o del file
                    If nome = True Then
                        'quindi aggiungo il carattere attuale al nome (vecchio metodo meno efficiente)
                        'str_nome = str_nome & carattere

                        'quindi prendo i caratteri da qui alla fine
                        'la prima volta che mi trovo qui, j punta al primo carattere del nome
                        'quindi con questa istruzione prendo il nome completo (visto che il nome è l'ultima cosa della riga)
                        str_nome = Mid(tree(i), j)
                        'imposto j per far terminare il ciclo
                        j = Len(tree(i))
                    Else
                        'se non sto ancora sui caratteri del nome
                        'ci possono essere questi caratteri
                        If carattere = "|" Or carattere = "\" Or carattere = " " Or carattere = "+" Then
                            'se sono questi aumento di 1 nodes (contatore dei nodi padri)
                            nodes = nodes + 1
                            'incremento di 3 j, che con il for sarà incrementato di un'altà unità
                            'per un complessivo di 4
                            'se ci fate caso, ogni nodo aggiuntivo, tree mette 4 caratteri (tra quelli sopra)
                            j = j + 3
                        Else
                            'altrimenti se non sono quei caratteri, il caratrtere è il primo del nome
                            nome = True
                            'decremento di 1, ma il for lo incrementerà di 1
                            'quindi il prossimo ciclo lo farà con lo stesso j, ma con nome=true
                            j = j - 1
                        End If
                    End If
                Next
                'adesso che ha fatto il parsing della linea
                'abbiamo su strnome il nome della cartella 

                'se non era una linea vuota
                If (str_nome) <> "" Then
                    'imposta a tmp_node il nodo iniziale
                    Dim tmp_node As TreeNode = FirstNode
                    'e iterativamente tmp_node
                    For j As Integer = 2 To nodes
                        'assumegli ultimi nodi figli, fino ad arrivare a nodes (il contatore)
                        'quindi quando j sarà uguale a tmp
                        'su tmp_node ci sarà il nodo a cui aggiungere il nome trovato
                        tmp_node = tmp_node.Nodes(tmp_node.Nodes.Count - 1)
                    Next
                    'qui lo aggiungiamo
                    tmp_node.Nodes.Add(str_nome)
                End If
                'resettiamo il conteggio
                nodes = 0
            Next
            'restituiamo FirstNode che conterrà tutti i nodi figli
            Return FirstNode
        Catch ex As Exception
            Throw
        End Try
    End Function

    'Funzione che dato una stringa multilinea, crea un'array i cui elementi
    'contengono ognuno una linea
    Public Function toLineArray(ByVal linee As String) As String()
        Try
            Return Split(linee, vbCrLf)
        Catch ex As Exception
            Throw
        End Try
    End Function
[/ot]
 
si più o meno quello.... in realtà la funzione deve prendere in input l'output del comando tree di windows (che sia su file o direttamente sulla console non è importante) e ricreare la struttura in un controllo treeview....

siccome c'è chi non sa usare la grafica ho deciso che va bene anche che il risultato sia formattato come testo, l'importante in quest'ultimo caso è non barare facendo semplicemente dei replace....

ah.... ci ho pensato solo adesso.... invece che l'output sotto forma di testo, si potrebbe creare proprio una struttura ad albero, ad esempio in c/c++ con strutture o oggetti.....
 
Giusto per far sapere che non sto lasciando perdere scrivo per dire che sto facendo proprio come hai detto tu whivel ^^ Sto creando una classe in c++ che preso in input un file lo trasforma in un albero da cui sarà molto semplice poi poter creare la struttura in un controllo grafico ;3
 
sono contento^^ effettivamente l'idea dell'albero è molto efficace se non si può o non si vuole fare direttamente lì'interfaccia grafica....

tra l'altro è utile anche per ricerche.... costruire un albero è la scelta migliore, soprattutto in c++....

[ot]bello il nuovo avatar^^[/ot]
 
[ot]thx =D[/ot]
Già tra l'altro una volta creato l'albero e intuitivo e molto veloce passare all'interfaccia. Credo che una volta finita la classe passerò a un'interfaccia con le wxWidgets per completezza ^^
 
interessante.... un mio amico ha fatto un catalogo per i file dei suoi dvd con i file di testo contenente il percorso e i nomi dei file (insomma non ha usato tree, ma l'elenco dei file con il percordo). quindi ogni file è un dvd.... da li l'idea di provarci e ho pensato al tree ^^

ha usato una lista e le wxwidgets...... voglio proprio vedere il risultato per confrontare ^^
 
Scusa, una domanda. Ma il senso del topic è creare un parser per il comando TREE o fare in modo che, dato il percorso di una cartella, tirare fuori tutte le cartelle al suo interno (o file) e metterle in una treeview?
 
creare un parser per il comando tree.... solo che il risultato deve essere in qualche modo visibile (è pur sempre un esercizio di programmazione)...

il meglio sarebbe un controllo treeview, ma siccome non tutti sanno usare la grafica nei vari linguaggi, ho pensato ad un output su file. Oppure, ed è l'alternativa migliore, di creare una struttura ad albero (come sta facendo solo)...
 
Stato
Discussione chiusa ad ulteriori risposte.