有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用文件以特定的方式打印目录树。newDirectoryStream和递归?

例如,我有一个文件夹“university”。我需要按如下方式打印“大学”内的所有文件夹和文件:

        university
        ├── file.txt
        ├── floor 1
        │   └── room 102
        │       └── file.txt
        ├── floor 2
        │   ├── left wing
        │   │   ├── kitchen
        │   │   │   └── kitchen.txt
        │   │   └── room 232
        │   └── right wing
        │       └── room 252
        │           ├── file1.txt
        │           └── file2.txt
        └── floor 3
            └── room 374
                └── file.txt

我被允许使用递归和文件。newDirectoryStream()方法或文件。将()列为模拟。我知道我的问题的一些解决方案,比如二叉树或类似的东西,但我只能使用我说的

这就是我所尝试的:

public class Main {
private static final String UNIVERSITY = "university";
private static final Path UNIVERSITY_FOLDER = Paths.get(UNIVERSITY);
private static final StringBuffer result = new StringBuffer();

public static void main(String[] args) throws IOException {
    createTree(UNIVERSITY_FOLDER);

}

private static void printTree(Path path) throws IOException {
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
        Iterator<Path> iter = stream.iterator();
        while (iter.hasNext()) {
            Path currentFile = iter.next();
            appendSpaces(currentFile);
            if (iter.hasNext()) {
                result.append("├── ");
            } else {
                result.append("└── ");
            }
            result.append(currentFile.getFileName());
            result.append(System.lineSeparator());
            if (Files.isDirectory(currentFile)) {
                printTree(currentFile);
            }
        }
    } catch (DirectoryIteratorException ex) {
        throw ex.getCause();
    }

}

private static void createTree(Path path) throws IOException {
    result.append(path.getFileName());
    result.append(System.lineSeparator());
    printTree(path);
    System.out.println(result.toString());
}

private static void appendSpaces(Path path) {
    for (int i = 0; i < (path.getNameCount() - 2); i++) {
        result.append("│   ");
    }
}

}

我的代码正在运行,但它打印出如下内容:

university
├── file.txt
├── floor 1
│   └── room 102
│   │   └── file.txt
├── floor 2
│   ├── left wing
│   │   ├── kitchen
│   │   │   └── kitchen.txt
│   │   └── room 232
│   └── right wing
│   │   └── room 252
│   │   │   ├── file1.txt
│   │   │   └── file2.txt
└── floor 3
│   └── room 374
│   │   └── file.txt

我需要打印此符号的附加条件“│“,但也许我走错了路。 如果有任何帮助,我将不胜感激


共 (1) 个答案

  1. # 1 楼答案

    正如您在252房间中看到的,当您printSpaces时,需要打印3个“缩进”,并且您的代码总是以缩进的形式打印"| "。但是252需要打印的是"| "第一个缩进,但是" "第二个和第三个缩进

    但是想象一下3楼有一个375房间,那么对于374房间的条目,你必须打印第一个缩进的" "和第二个缩进的"| "

    这表明打印缩进的代码从根本上被破坏了。当前,该代码只传递了一个数字,其中列出了要打印的缩进数量。它需要传递数组或其他类似列表的结构。你不会通过“3”,而是通过“真、假、假”或类似的内容

    更糟糕的是,您目前将文件名传递给appendSpaces,并编写一些代码对其进行路径深度分析,以了解甚至有多少缩进,这只是一个非起始点:给定的路径只是无法知道每个缩进的,无论您是需要画线还是只需要一个空白块

    有很多解决方案,但最常用的是使用递归助手。对于大多数递归算法,您需要一些跟踪信息的变量,例如“多少缩进”(或者在本例中,一组标志,每个缩进一个,以指示是否绘制条形图)。对于第一个调用(代码的用户所做的调用),这些跟踪器变量没有意义,因此您可以创建一个助手。因此,不是:

    public static void printTree(... params ...) {
       // code that will eventaully call printTree recursively
    }
    

    你可以这样做:

    public static void printTree(.... params ...) {
        printTree0(param1, param2, param3, new boolean[0]);
    }
    
    private static void printTree0(... params ..., boolean[] indents) {
        // code that calls printTree0 recursively
    }
    

    这是一种非常常见的模式:

    • public方法只包含一个调用private方法的一行程序,以相同的顺序传递所有参数,另外还有一些变量,都是初始值(0,或者在本例中是一个空布尔数组,表示根级别不需要缩进)

    • 私有方法(附加0是一种有点常见的java习语,用来表示“这是一个助手方法”)是递归编写的,而公共方法则不是

    您的indentstracker变量包含这些标志,指示是否打印条

    每次递归时,创建一个新的布尔数组,添加正确的缩进:

    boolean[] newIndents = Arrays.copyOf(indents, indents.length + 1);
    newIndents[indents.length] = true or false (depending on whether you want bars or not).
    

    从那里我相信你能弄明白,因为你几乎完成了任务