Java Tree to represent filesystem (files/dir) from list of paths

前端 未结 5 687
感动是毒
感动是毒 2021-02-04 02:39

I\'ve a list of paths like this

/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/sdc         


        
相关标签:
5条回答
  • 2021-02-04 03:06

    I would recommend reading up on data structures, particularly trees. In Java, you can represent these by creating a node class that has references to other nodes. For example:

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

    Obviously, you can store your node references anyway you like- arrays or collections will work with non-binary trees.

    Given your list of files, you can read these and populate your tree structure.

    0 讨论(0)
  • 2021-02-04 03:15

    Seems like you could adapt either a Trie / Radix Trie or a Binary Search Tree to work in either situation. You could augment a Trie to store "folders" as the inner nodes (instead of characters like in a regular Trie) or you could augment a Binary Search Tree to store "folders" as inner nodes (as long as they implement a comparable interface) and "files" as leaf nodes.

    My implementation of those structures are linked in the text above.

    0 讨论(0)
  • 2021-02-04 03:21

    Thank you for all your answer. I made my working implementation. I think that I will need to improve it in order to make it works better with more caching in adding element to the tree structure.

    As I said what I was needing was a structure that allow me to have a "virtual" rappresentation of a 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;
        }
    
    
    }
    

    Test.java for test code

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

    Please tell me if you have some good advice about improvments :)

    0 讨论(0)
  • 2021-02-04 03:26

    I implemented a solution to the challenge myself, it is available as a GitHubGist.

    I am representing each node of a filesystem-hierarchy in a DirectoryNode. A helper-method createDirectoryTree(String[] filesystemList) creates a direcotry-tree.

    Here is the usage example, which is included in the 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);
    

    The System.out.println -output is:

      {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=[]}]}]}
    
    0 讨论(0)
  • 2021-02-04 03:26

    Have a look in new Java 7 - nio2 package. All you need is inside.

    0 讨论(0)
提交回复
热议问题