2012-06-07 11 views
17

tengo una lista de rutas como estaárbol de Java para representar el sistema de archivos (archivos/dir) de la lista de rutas de

/mnt/sdcard/folder1/a/b/file1 
/mnt/sdcard/folder1/a/b/file2 
/mnt/sdcard/folder1/a/b/file3 
/mnt/sdcard/folder1/a/b/file4 
/mnt/sdcard/folder1/a/b/file5 
/mnt/sdcard/folder1/e/c/file6 
/mnt/sdcard/folder2/d/file7 
/mnt/sdcard/folder2/d/file8 
/mnt/sdcard/file9 

Así que de esta lista de rutas (picaduras) Necesito a Creta una estructura de árbol de Java que tiene carpetas como nodos y archivos como hoja (no habrá carpetas vacías como hoja).

Lo que necesito Creo que es el método add donde les paso una cadena (ruta del archivo) y lo agrega al lugar correcto en el árbol creando nodos correctos (Carpeta) si no están ya allí

esta estructura de árbol me tendrá que obtener la lista de nodos cuando estoy en el nodo y la lista de hojas (pero creo que esto será una serie de características normales de los árboles)

siempre tendrán cadenas como caminos y no archivo real o carpetas. ¿Hay algo listo para usar o un código fuente para comenzar?

Muchas gracias.

+0

* "código fuente para empezar?" * Ver [Explorador de archivos GUI] (http://codereview.stackexchange.com/questions/4446/archivo-navegador-gui). –

+0

** Vea también: ** http://stackoverflow.com/questions/1005551/construct-a-tree-structure-from-list-of-string-paths – dreftymac

Respuesta

21

Gracias por toda tu respuesta. Hice mi implementación de trabajo. Creo que tendré que mejorarlo para que funcione mejor con más almacenamiento en caché para agregar elementos a la estructura del árbol.

Como dije lo que necesitaba era una estructura que me permitiera tener una representación "virtual" de un FS.

MXMTree.java

public class MXMTree { 

    MXMNode root; 
    MXMNode commonRoot; 

    public MXMTree(MXMNode root) { 
     this.root = root; 
     commonRoot = null; 
    } 

    public void addElement(String elementValue) { 
     String[] list = elementValue.split("/"); 

     // latest element of the list is the filename.extrension 
     root.addElement(root.incrementalPath, list); 

    } 

    public void printTree() { 
     //I move the tree common root to the current common root because I don't mind about initial folder 
     //that has only 1 child (and no leaf) 
     getCommonRoot(); 
     commonRoot.printNode(0); 
    } 

    public MXMNode getCommonRoot() { 
     if (commonRoot != null) 
      return commonRoot; 
     else { 
      MXMNode current = root; 
      while (current.leafs.size() <= 0) { 
       current = current.childs.get(0); 
      } 
      commonRoot = current; 
      return commonRoot; 
     } 

    } 


} 

MXMNode.java

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 


public class MXMNode { 

    List<MXMNode> childs; 
    List<MXMNode> leafs; 
    String data; 
    String incrementalPath; 

    public MXMNode(String nodeValue, String incrementalPath) { 
     childs = new ArrayList<MXMNode>(); 
     leafs = new ArrayList<MXMNode>(); 
     data = nodeValue; 
     this. incrementalPath = incrementalPath; 
    } 

    public boolean isLeaf() { 
     return childs.isEmpty() && leafs.isEmpty(); 
    } 

    public void addElement(String currentPath, String[] list) { 

     //Avoid first element that can be an empty string if you split a string that has a starting slash as /sd/card/ 
     while(list[0] == null || list[0].equals("")) 
      list = Arrays.copyOfRange(list, 1, list.length); 

     MXMNode currentChild = new MXMNode(list[0], currentPath+"/"+list[0]); 
     if (list.length == 1) { 
      leafs.add(currentChild); 
      return; 
     } else { 
      int index = childs.indexOf(currentChild); 
      if (index == -1) { 
       childs.add(currentChild); 
       currentChild.addElement(currentChild.incrementalPath, Arrays.copyOfRange(list, 1, list.length)); 
      } else { 
       MXMNode nextChild = childs.get(index); 
       nextChild.addElement(currentChild.incrementalPath, Arrays.copyOfRange(list, 1, list.length)); 
      } 
     } 
    } 

    @Override 
    public boolean equals(Object obj) { 
     MXMNode cmpObj = (MXMNode)obj; 
     return incrementalPath.equals(cmpObj.incrementalPath) && data.equals(cmpObj.data); 
    } 

    public void printNode(int increment) { 
     for (int i = 0; i < increment; i++) { 
      System.out.print(" "); 
     } 
     System.out.println(incrementalPath + (isLeaf() ? " -> " + data : "") ); 
     for(MXMNode n: childs) 
      n.printNode(increment+2); 
     for(MXMNode n: leafs) 
      n.printNode(increment+2); 
    } 

    @Override 
    public String toString() { 
     return data; 
    } 


} 

prueba.java para el código de prueba

public class Test { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 

     String slist[] = new String[] { 
       "/mnt/sdcard/folder1/a/b/file1.file", 
       "/mnt/sdcard/folder1/a/b/file2.file", 
       "/mnt/sdcard/folder1/a/b/file3.file", 
       "/mnt/sdcard/folder1/a/b/file4.file", 
       "/mnt/sdcard/folder1/a/b/file5.file", 
       "/mnt/sdcard/folder1/e/c/file6.file", 
       "/mnt/sdcard/folder2/d/file7.file", 
       "/mnt/sdcard/folder2/d/file8.file", 
       "/mnt/sdcard/file9.file" 
     }; 

     MXMTree tree = new MXMTree(new MXMNode("root", "root")); 
     for (String data : slist) { 
      tree.addElement(data); 
     } 

     tree.printTree(); 
    } 

} 

Por favor, dígame si usted tiene un buen consejo sobre alguna mejora :)

+0

Creo que una buena manera de mejorarlo sería agregar una forma fácil de atravesar el árbol. Aparte de eso, buen trabajo – user489041

+0

¡Buen ejemplo de código! – 23ars

-1

Eche un vistazo en el nuevo Java 7 - nio2 package. Todo lo que necesitas es adentro.

+0

Esto es útil pero no toma una lista de texto rutas como entrada, lo cual está bien si, literalmente, desea navegar un sistema de archivos real. Pero en mi caso quiero guardar en caché mi sistema de archivos virtual (abstracción de una base de datos) en un archivo txt. –

1

Yo recomendaría leer en data structures, en particular trees. En Java, puede representarlos creando una clase de nodo que tenga referencias a otros nodos. Por ejemplo:

public class Node { 
    private Node[] children; 
    /* snip other fields */ 
    public boolean isFile() { 
     return children.count == 0; 
    } 
} 

Obviamente, puede almacenar sus referencias de nodos de todos modos le gusta- matrices o colecciones trabajará con árboles no binarios.

Dada su lista de archivos, puede leerlos y completar su estructura de árbol.

2

Parece que podría adaptar un Trie/Radix Trie o un Binary Search Tree para funcionar en cualquier situación. Podría aumentar un Trie para almacenar "carpetas" como los nodos internos (en lugar de caracteres como en un Trie normal) o podría aumentar un árbol de búsqueda binaria para almacenar "carpetas" como nodos internos (siempre que implementen una interfaz comparable) y "archivos" como nodos hoja.

Mi implementación de esas estructuras está vinculada en el texto anterior.

0

he implementado una solución al desafío a mí mismo, es available as a GitHubGist.

Represento cada nodo de una jerarquía de sistema de archivos en un DirectoryNode. Un método auxiliar createDirectoryTree (String [] filesystemList) crea un árbol direcotry.

Aquí está el ejemplo de uso, que se incluye en el GitHubGist.

final String[] list = new String[]{ 
    "/mnt/sdcard/folder1/a/b/file1.file", 
    "/mnt/sdcard/folder1/a/b/file2.file", 
    "/mnt/sdcard/folder1/a/b/file3.file", 
    "/mnt/sdcard/folder1/a/b/file4.file", 
    "/mnt/sdcard/folder1/a/b/file5.file", 
    "/mnt/sdcard/folder1/e/c/file6.file", 
    "/mnt/sdcard/folder2/d/file7.file", 
    "/mnt/sdcard/folder2/d/file8.file", 
    "/mnt/sdcard/file9.file" 
}; 

final DirectoryNode directoryRootNode = createDirectoryTree(list); 

System.out.println(directoryRootNode); 

El System.out.println -output es:

{value='mnt', children=[{value='sdcard', children=[{value='folder1', 
    children=[{value='a', children=[{value='b', children=[{value='file1.file', 
    children=[]}, {value='file2.file', children=[]}, {value='file3.file', 
    children=[]}, {value='file4.file', children=[]}, {value='file5.file', 
    children=[]}]}]}, {value='e', children=[{value='c', 
    children=[{value='file6.file', children=[]}]}]}]}, 
    {value='folder2', children=[{value='d', children=[{value='file7.file', 
    children=[]}, {value='file8.file', children=[]}]}]}, 
    {value='file9.file', children=[]}]}]} 
Cuestiones relacionadas