2011-12-23 7 views
5

que tienen una matriz de cadenas de algunas rutas de archivos:¿Cómo puedo convertir una lista de nombres de archivo a una estructura de árbol?

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

¿Cómo puedo convertir esta lista para una estructura de árbol? Hasta ahora tengo lo siguiente:

/// <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"); 
     } 
    } 
} 

Estoy un poco perdido en la forma de dividir los caminos y todo. Cualquier ruta que termine con/es un directorio, cualquiera que no lo haga, no lo es.

Además, aunque mi entrada siempre contendrá una ruta a la carpeta, ¿cómo podría explicar esa situación si no fuera así?

Por ejemplo, si tuviera la entrada:

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

Cómo me gustaría tener en cuenta el hecho de que path/to/ no se encuentra en la entrada?

Respuesta

5

Aquí es una solución que genera un diccionario anidada de elementos NodeEntry (se puede sustituir la clase de información de archivo, según sea necesario):

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); 
      } 
     } 
    } 
} 

Para utilizar el anterior, crear una nueva colección:

 NodeEntryCollection cItems = new NodeEntryCollection(); 

entonces, para cada línea de la lista:

 cItems.AddEntry(sLine, 0); 
+0

Esto me llevó a donde necesitaba, muchas gracias mucho! –

+0

Se agregó resumen de esto aquí: https://gist.github.com/2282389 (para su conveniencia) –

+0

Cómo seleccionar los elementos secundarios de un subnodo, por ejemplo, cómo obtener elementos secundarios de 'subdirectorio' en' directorio1/subdirectorio/archivos' ? –

0

Dividir cada línea por el carácter '/'. Si la matriz de cadenas es de longitud 5, entonces los primeros cuatro elementos deben ser directorios, y usted tiene que probar la última de una extensión:

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

Si, como en su caso, siempre hay una '/' incluso para el último directorio, luego el último elemento de la matriz de cadenas divididas está vacío.

El resto se trata de atravesar su árbol. Al analizar un elemento, verifique si existe el primer directorio en la propiedad Children de su nodo raíz. Si no existe, agréguelo, si lo hace, use este y vaya más allá.

Cuestiones relacionadas