在java中打印从root到child的平面目录结构

时间:2018-01-20 09:46:20

标签: java python file data-structures tree

我有一个平面文件目录结构存储在包含

的csv文件中
id; parentId; name; type; size; classification; checksum;
1;3;file1;file;10;Secret;42;
2; ;folder2;directory; ; ; ;
3;11;folder3;directory; ; ; ;
4;2;file4;file;40;Secret;42;
5;3;file5;file;50;Public;42;
6;3;file6;file;60;Secret;42;
7;3;file7;file;70;Public;42;
8;10;file8;file;80;Secret;42;
9;10;file9;file;90;Top secret;42;
10;11;folder10;directory; ; ; ;
11;2;folder11;directory; ; ; ;

Image showing the tree structure

我们需要使用id和parent id将结构排列为树层次结构。我能够在哪里手动完成 它在图中显示出来。但是当涉及到编码时,我无法使用正确的数据结构找到确切的解决方案。 输出应该是根文件夹的形式到基础文件夹或文件时打印它应该打印的文件夹 该文件夹中的文件和文件夹的大小。适当的java或python解决方案将很有帮助

name = folder2, type = Directory, size = 400
name = file4, type = File, size = 40, classification = Secret, checksum = 42
name = folder11, type = Directory, size = 360
name = folder10, type = Directory, size = 170
name = file8, type = File, size = 80, classification = Secret, checksum = 42
name = file9, type = File, size = 90, classification = Top secret, checksum = 42
name = folder3, type = Directory, size = 190
name = file1, type = File, size = 10, classification = Secret, checksum = 42
name = file5, type = File, size = 50, classification = Public, checksum = 42
name = file6, type = File, size = 60, classification = Secret, checksum = 42
name = file7, type = File, size = 70, classification = Public, checksum = 42

2 个答案:

答案 0 :(得分:0)

这是一个非常基本的Java实现。

    HashMap<String, Set<String>> nodes = new HashMap<>();
    File file = new File("E:/test.txt");

    try (Stream<String> stream = Files.lines(file.toPath())) {
        stream.forEach((line) -> {
            String parts[] = line.split(";");
            nodes.putIfAbsent(parts[0], new HashSet<>());
            nodes.putIfAbsent(parts[1], new HashSet<>());
            nodes.get(parts[1]).add(parts[0]);
        });
    } catch (Exception e) {
        e.printStackTrace();
    }

以上代码将子文件映射到其父项。这是一种实现树的惰性方法,其中您了解所有节点及其子节点,这是平面文件目录结构中显示的所有信息。它逐行流式传输文件;在每行中它获取节点id和父id,如果在将节点id添加到父id子集之前它们不存在,则为它们中的任何一个创建节点。

在这个阶段,节点HashMap看起来像这样:

{ =[2], 11=[3, 10], 1=[], 2=[11, 4], 3=[1, 5, 6, 7], 4=[], 5=[], 6=[], 7=[], 8=[], 9=[], 10=[8, 9]}

如果您对将" "字符串视为根感到满意,则可以通过检索根nodes.get(" ");开始递归遍历列表,否则您将需要定义如何检索根节点

在维护信息的同时采用这种方法的一种可能方法是将每个文件视为节点。

public static void main (String args[]) {
    HashMap<Node, Set<Node>> nodes = new HashMap<>();
    File file = new File("E:/test.txt");

    try (Stream<String> stream = Files.lines(file.toPath())) {
        stream.forEach((line) -> {
            String parts[] = line.split(";");
            Node node = new Node(parts);
            Node parent = new Node(parts[1]);

            nodes.putIfAbsent(parent, new HashSet<>());
            nodes.putIfAbsent(node, new HashSet<>());
            nodes.get(parent).add(node);
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
    calculateSize(nodes, new Node(" "));
    traverse(nodes, new Node(" "));

}

public static void traverse(HashMap<Node, Set<Node>> nodes, Node root) {
    System.out.println(root);
    for (Node child : nodes.get(root)) {
        traverse(nodes, child);
    }
}

public static int calculateSize(HashMap<Node, Set<Node>> nodes, Node root) {
    int size = root.getSize();
    for (Node child : nodes.get(root)) {
        size += calculateSize(nodes, child);
    }
    root.setSize(size);
    return size;
}

public static class Node {
    private String id = " ";
    private String type= " ";
    private String name = " ";
    private int size = 0;
    private String classification = " ";
    private int checksum = 0;

    public Node (String[] parts) {
        this.id = parts[0];
        this.name = parts[2];
        this.type = parts[3];
        this.classification = parts[5];
        if (this.type.equals("file")) {

            this.size = Integer.parseInt(parts[4]);
            this.checksum = Integer.valueOf(parts[6]);
        }
    }

    public Node (String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        if (name.equals(" ")) return "Root";
        String toString = (name.equals(" ")) ? "" : String.format("name = %s", name);
        toString += (type.equals(" ")) ? "" : String.format(", type = %s", type);
        toString += String.format(", size = %d", size);
        toString += (classification.equals(" ")) ? "" : String.format(", classification = %s", classification);
        toString += String.format(", checksum = %d", checksum);
        return toString;
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof Node) {
            return ((Node) o).id.equals(this.id);
        } else if (o instanceof String) {
            return o.equals(this.id);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return this.id.hashCode();
    }

    public int getSize() { return size; }
    public void setSize(int size) { this.size = size; }
}

递归搜索允许您遍历节点并将其打印到控制台。注意我已经覆盖了equals,hashCode和toString方法。 equals和hashCode允许您避免重复并确保保留节点关联。

如果您想要对文件求和,您可以按照我的建议使用递归来计算特定目录及其所有子目录的总和。

你的问题非常不清楚你想要什么。下次请更清楚。

作为旁注:你的图表不正确。 7只是3的子目录,而不是10。

答案 1 :(得分:-1)

您可以制作2个课程FileFolder,您可以在这些课程中覆盖所需的__str__()方法。