2011-12-23 7 views
5

Ho un array di stringhe di alcuni percorsi di file:Come posso convertire una lista di nomi di file in una struttura ad albero?

path/to/folder/file.xxx 
path/to/other/ 
path/to/file/file.xx 
path/file.x 
path/ 

Come posso convertire questo elenco per una struttura ad albero? Finora ho il seguente:

/// <summary> 
/// Enumerates types of filesystem nodes. 
/// </summary> 
public enum FilesystemNodeType 
{ 
    /// <summary> 
    /// Indicates that the node is a file. 
    /// </summary> 
    File, 

    /// <summary> 
    /// Indicates that the node is a folder. 
    /// </summary> 
    Folder 
} 

/// <summary> 
/// Represents a file or folder node. 
/// </summary> 
public class FilesystemNode 
{ 
    private readonly ICollection<FilesystemNode> _children; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="FilesystemNode"/> class. 
    /// </summary> 
    public FilesystemNode() 
    { 
     _children = new LinkedList<FilesystemNode>(); 
    } 

    /// <summary> 
    /// Gets or sets the name of the file or folder. 
    /// </summary> 
    public string Name { get; set; } 

    /// <summary> 
    /// Gets or sets the full path to the file or folder from the root. 
    /// </summary> 
    public string Path { get; set; } 

    /// <summary> 
    /// Gets or sets a value indicating whether the node is a file or folder. 
    /// </summary> 
    public FilesystemNodeType Type { get; set; } 

    /// <summary> 
    /// Gets a list of child nodes of this node. The node type must be a folder to have children. 
    /// </summary> 
    public ICollection<FilesystemNode> Children 
    { 
     get 
     { 
      if (Type == FilesystemNodeType.Folder) 
       return _children; 

      throw new InvalidOperationException("File nodes cannot have children"); 
     } 
    } 
} 

Sono solo un po 'in perdita su come effettivamente ripartire i percorsi e tutto. Qualsiasi percorso che termina con un/è una directory, nessuno che non lo fa, non lo è.

Inoltre, mentre il mio input conterrà sempre un percorso per la cartella, come dovrei tenere conto di quella situazione se non lo fosse?

Per esempio, se ho avuto l'input:

path/to/file.c 
path/file.c 
path/ 

Come faccio a spiegare il fatto che path/to/ non è in ingresso?

risposta

5

Ecco una soluzione che genera un dizionario nidificato di oggetti NodeEntry (è possibile sostituire la classe informazioni del file in base alle esigenze):

public class NodeEntry 
{ 
    public NodeEntry() 
    { 
     this.Children = new NodeEntryCollection(); 
    } 

    public string Key { get; set; } 
    public NodeEntryCollection Children { get; set; } 

} 

public class NodeEntryCollection : Dictionary<string, NodeEntry> 
{ 
    public void AddEntry(string sEntry, int wBegIndex) 
    { 
     if (wBegIndex < sEntry.Length) 
     { 
      string sKey; 
      int wEndIndex; 

      wEndIndex = sEntry.IndexOf("/", wBegIndex); 
      if (wEndIndex == -1) 
      { 
       wEndIndex = sEntry.Length; 
      } 
      sKey = sEntry.Substring(wBegIndex, wEndIndex - wBegIndex); 
      if (!string.IsNullOrEmpty(sKey)) { 
       NodeEntry oItem; 

       if (this.ContainsKey(sKey)) { 
        oItem = this[sKey]; 
       } else { 
        oItem = new NodeEntry(); 
        oItem.Key = sKey; 
        this.Add(sKey, oItem); 
       } 
       // Now add the rest to the new item's children 
       oItem.Children.AddEntry(sEntry, wEndIndex + 1); 
      } 
     } 
    } 
} 

Per utilizzare quanto sopra, creare una nuova collezione:

 NodeEntryCollection cItems = new NodeEntryCollection(); 

poi, per ogni linea nella vostra lista:

 cItems.AddEntry(sLine, 0); 
+0

Questo mi ha fatto al punto in cui avevo bisogno, vi ringrazio tanto! –

+0

Sintesi di questo aggiunto qui: https://gist.github.com/2282389 (per praticità) –

+0

Come selezionare i bambini da un sottonodo, ad esempio come richiamare i bambini da 'sottodirectory' in' directory1/sottodirectory/file' ? –

0

Dividere ogni riga con il carattere '/'. Se la matrice di stringhe è di lunghezza 5, quindi i primi quattro articoli dovrebbero essere le directory, e si deve testare l'ultima di una proroga:

string.IsNullOrEmpty(new FileInfo("test").Extension) 

Se, come nel tuo caso, c'è sempre un '/' anche per l'ultima directory, quindi l'ultimo elemento dell'array della stringa divisa è vuoto.

Il resto è solo per attraversare il tuo albero. Durante l'analisi di un elemento, controllare se la prima directory esiste nella proprietà Children del nodo radice. Se non esiste, aggiungilo, se lo fa, usa questo e vai oltre.