Эта часть класса отвечает за создание каталогов и файлов и добавление их.

public class TreeNode<T> implements Iterable<TreeNode<T>> {

    public T data;
    public TreeNode<T> parent;
    public List<TreeNode<T>> children;

    public boolean isRoot() {
        return parent == null;
    }

    private List<TreeNode<T>> elementsIndex;

    public TreeNode(T data) {
        this.data = data;
        this.children = new LinkedList<TreeNode<T>>();
        this.elementsIndex = new LinkedList<TreeNode<T>>();
        this.elementsIndex.add(this);
    }

    public TreeNode<T> addChild(T child) {
        TreeNode<T> childNode = new TreeNode<T>(child);
        childNode.parent = this;
        this.children.add(childNode);
        this.registerChildForSearch(childNode);
        return childNode;
    }

    private void registerChildForSearch(TreeNode<T> node) {
        elementsIndex.add(node);
        if (parent != null)
            parent.registerChildForSearch(node);
    }

    @Override
    public String toString() {
        return data != null ? data.toString() : "[data null]";
    }

    @Override
    public Iterator<TreeNode<T>> iterator() {
        TreeNode<T> iter = new TreeNode<T>((T) this);
        return (Iterator<TreeNode<T>>) iter;
    }

    public static TreeNode<File> createDirTree(File folder) {
        if (!folder.isDirectory()) {
            throw new IllegalArgumentException("folder is not a Directory");
        }
        TreeNode<File> DirRoot = new TreeNode<File>(folder);
        for (File file : folder.listFiles()) {
            if (file.isDirectory()) {
                appendDirTree(file, DirRoot);
            } else {
                appendFile(file, DirRoot);
            }}
        return DirRoot;
    }

    public static void appendDirTree(File folder, TreeNode<File> DirRoot) {
        DirRoot.addChild(folder);
        for (File file : folder.listFiles()) {
            if (file.isDirectory()) {
                appendDirTree(file, DirRoot.children.get(DirRoot.children.size() - 1));
            } else {
                appendFile(file, DirRoot.children.get(DirRoot.children.size() - 1));
            }} }

    public static void appendFile(File file, TreeNode<File> filenode) {
        filenode.addChild(file);
    }

Проблема в том, что в этом состоянии кода файлы и каталоги печатаются следующим образом:

rootFolder   
├─ Folder1 
│  ├─ subFolder1 
│  │  ├─ a.txt  
│  │  ├─ b.txt 
│  │  ├─ c.txt  
│  │  └─ d.txt  
│  ├─ subFolder2  
│  │  ├─ a.txt  
│  │  ├─ B.txt  
│  │  ├─ c.txt  
│  │  └─ D.txt  
│  ├─ subFolder3 
│  │  ├─ A.txt  
│  │  ├─ b.txt  
│  │  ├─ C.txt  
│  │  └─ d.txt  
│  └─ subFolder4 
│      ├─ a.txt  
│      ├─ b.txt 
│      ├─ c.txt 
│      └─ d.txt 
├─ File1.txt  
├─ Folder2  
│  ├─ a.txt 
│  ├─ b.txt 
│  ├─ c.txt 
│  └─ d.txt 
└─ File2.txt

Но мне нужны сначала каталоги, а затем файлы: File1.txt рядом с File2.txt. Я пытаюсь найти причину проблемы, но безуспешно. Что мне нужно изменить и где в коде получить желаемый результат?

1
Richard Walker 27 Ноя 2021 в 11:45
Привет Ричард Уокер, пожалуйста, просмотрите это stackoverflow.com/questions/10655085/print-directory-tree
 – 
hani
27 Ноя 2021 в 12:03
Отвечает ли это на ваш вопрос? распечатать дерево каталогов
 – 
Vojin Purić
27 Ноя 2021 в 12:25
Я знаю этот пост, но он не отвечает именно на этот вопрос
 – 
Richard Walker
27 Ноя 2021 в 16:43

1 ответ

Лучший ответ

Проблема в том, в каком порядке вы добавляете дочерние деревья.

Как В документации по Java сказано для .listFiles():

Нет гарантии, что строки имен в результирующем массиве появятся в каком-либо определенном порядке; в частности, не гарантируется их появление в алфавитном порядке.

Поэтому вам нужно отсортировать файлы перед их добавлением.

Вот возможное решение для методов createDirTree и appendDirTree.

(Примечание: сортировка основана только на том, если он s a directory or not. If you need another custom sorting, you need to adapt the Comparator`)

public static TreeNode<File> createDirTree(File folder) {
  if (!folder.isDirectory()) {
    throw new IllegalArgumentException("folder is not a Directory");
  }

  List<File> children = Arrays.asList(folder.listFiles());
  children.sort(Comparator.comparing(file -> file.isDirectory() ? -1 : 1));

  TreeNode<File> DirRoot = new TreeNode<File>(folder);
  for (File file : children) {
    if (file.isDirectory()) {
      appendDirTree(file, DirRoot);
    } else {
      appendFile(file, DirRoot);
    }}
  return DirRoot;
}

public static void appendDirTree(File folder, TreeNode<File> dirRoot) {
  dirRoot.addChild(folder);

  List<File> children = Arrays.asList(folder.listFiles());
  children.sort(Comparator.comparing(file -> file.isDirectory() ? -1 : 1));

  for (File file : children) {
    if (file.isDirectory()) {
      appendDirTree(file, dirRoot.children.get(dirRoot.children.size() - 1));
    } else {
      appendFile(file, dirRoot.children.get(dirRoot.children.size() - 1));
    }
  }
}

Есть несколько способов добиться этого. Например. вы также можете использовать потоки. См. Пример для createDirTree ниже:

public static TreeNode<File> createDirTree(File folder) {
  if (!folder.isDirectory()) {
    throw new IllegalArgumentException("folder is not a Directory");
  }
  TreeNode<File> DirRoot = new TreeNode<File>(folder);
  
  Arrays.stream(folder.listFiles())
      .sorted(Comparator.comparing(f -> (f.isDirectory() ? 1 : -1)))
      .forEach(file -> {
        if (file.isDirectory()) {
          appendDirTree(file, DirRoot);
        } else {
          appendFile(file, DirRoot);
        }
      });
  return DirRoot;
}
0
csalmhof 27 Ноя 2021 в 15:18