16

I have to print a directory tree (like tree command), example:

 .
 +---A
 |   +---IMAGES
 |       +---BACKUP
 +---ADOKS
 |   +---ROZDZIAL_2
 |   +---ROZDZIAL_3
 |   +---ROZDZIAL_4
 +---AMSC2005
 |   +---AMSC2004
 +---FCCS2005
 |   +---source
 |   +---TMP
 +---LODZ2004
 +---ZAKOPANE2004
 +---DYDAKTYKA
 |   +---DYDAKTYKA_ISI
 |   |   +---COLLS
 |   |   |   +---Q1
 |   |   |   +---Q2
 |   |   |   +---RAZEM
 |   |   |       +---RYSUNKI_COLL1
 |   |   |       +---RYSUNKI_COLL2
 |   |   +---IMAGES
 |   |   +---src
 |   |   +---WYKLAD5
 |   +---DYDAKTYKA_PRG
 |       +---images
 |       +---POMOC
 +---DYDAKTYKA_KST
 |   +---images
 |   +---src
 +---DYDAKTYKA_WPR
     +---images
     +---src

I tried with the following Code:

private static void getInto(String p, int n) {
    File path = new File(p);
    File[] list = path.listFiles();

    for (int i = 0; i < list.length; i++) {
        if (list[i].isDirectorhowny()) {
            for (int j = 0; j < n; j++)
                if (WHAT HERE?)
                    System.out.print("|  ");
                else
                    System.out.print("   ");

            System.out.println("+--" + list[i].getName().toString());

            getInto(list[i].getPath(), n + 1);
        }
    }
}

I tried few version, but it's still not work. How to do this? What condition should be put in If? I know is pretty simple, but I can't do this.

xlecoustillier
  • 16,183
  • 14
  • 60
  • 85
user1248092
  • 361
  • 1
  • 6
  • 19

11 Answers11

32

This is how I did it.

The Code

import java.io.File;
public class FileAssert {

/**
 * Pretty print the directory tree and its file names.
 * 
 * @param folder
 *            must be a folder.
 * @return
 */
public static String printDirectoryTree(File folder) {
    if (!folder.isDirectory()) {
        throw new IllegalArgumentException("folder is not a Directory");
    }
    int indent = 0;
    StringBuilder sb = new StringBuilder();
    printDirectoryTree(folder, indent, sb);
    return sb.toString();
}

private static void printDirectoryTree(File folder, int indent,
        StringBuilder sb) {
    if (!folder.isDirectory()) {
        throw new IllegalArgumentException("folder is not a Directory");
    }
    sb.append(getIndentString(indent));
    sb.append("+--");
    sb.append(folder.getName());
    sb.append("/");
    sb.append("\n");
    for (File file : folder.listFiles()) {
        if (file.isDirectory()) {
            printDirectoryTree(file, indent + 1, sb);
        } else {
            printFile(file, indent + 1, sb);
        }
    }

}

private static void printFile(File file, int indent, StringBuilder sb) {
    sb.append(getIndentString(indent));
    sb.append("+--");
    sb.append(file.getName());
    sb.append("\n");
}

private static String getIndentString(int indent) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < indent; i++) {
        sb.append("|  ");
    }
    return sb.toString();
}
}

The Result

+--folder1/
|  +--a.txt
|  +--folder2/
|  |  +--b1.txt
|  |  +--b2.txt
|  |  +--b3.txt
|  |  +--folder3/
|  +--folder4/

The UnitTest

import static org.junit.Assert.*;

import java.io.File;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class FileAssertTest {

@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private File folder1;

@Before
public void setUp() {
    folder1 = temporaryFolder.newFolder("folder1");
}

@Test
public void testPrintDirectoryTreeWhenFolderIsEmpty() {
    // Invoke
    String actual = FileAssert.printDirectoryTree(folder1);
    // Verify
    assertEquals("+--folder1/\n", actual);
}

private static final String EXPECTED_FCOF = "" + "+--folder1/\n"
        + "|  +--a.txt\n";

@Test
public void testPrintDirectoryTreeWhenFolderContainsOneFile()
        throws Exception {
    // Setup
    File aFile = new File(folder1, "a.txt");
    assertTrue(aFile.createNewFile());
    // Invoke
    String actual = FileAssert.printDirectoryTree(folder1);
    // Verify
    assertEquals(EXPECTED_FCOF, actual);
}

private static final String EXPECTED_COMPLEX = "+--folder1/\n"
        + "|  +--a.txt\n" + "|  +--folder2/\n" + "|  |  +--b1.txt\n"
        + "|  |  +--b2.txt\n" + "|  |  +--b3.txt\n" + "|  |  +--folder3/\n"
        + "|  +--folder4/\n";

@Test
public void testPrintDirectoryTreeComplex() throws Exception {
    // Setup
    File aFile = new File(folder1, "a.txt");
    assertTrue(aFile.createNewFile());
    File folder2 = new File(folder1, "folder2");
    assertTrue(folder2.mkdir());
    File b1File = new File(folder2, "b1.txt");
    assertTrue(b1File.createNewFile());
    File b2File = new File(folder2, "b2.txt");
    assertTrue(b2File.createNewFile());
    File folder3 = new File(folder2, "folder3");
    assertTrue(folder3.mkdir());
    File b3File = new File(folder2, "b3.txt");
    assertTrue(b3File.createNewFile());
    File folder4 = new File(folder1, "folder4");
    assertTrue(folder4.mkdir());

    // Invoke
    String actual = FileAssert.printDirectoryTree(folder1);
    // Verify
    assertEquals(EXPECTED_COMPLEX, actual);
}

}

TAN70
  • 583
  • 7
  • 9
8

This is my solution:

(The TreeNode Class is copied from there.)

public static String renderDirectoryTree(TreeNode<FileInformation> tree) {
    List<StringBuilder> lines = renderDirectoryTreeLines(tree);
    String newline = System.getProperty("line.separator");
    StringBuilder sb = new StringBuilder(lines.size() * 20);
    for (StringBuilder line : lines) {
        sb.append(line);
        sb.append(newline);
    }
    return sb.toString();
}

public static List<StringBuilder> renderDirectoryTreeLines(TreeNode<FileInformation> tree) {
    List<StringBuilder> result = new LinkedList<>();
    result.add(new StringBuilder().append(tree.getData().getPath().getFileName()));
    Iterator<TreeNode<FileInformation>> iterator = tree.getChildren().iterator();
    while (iterator.hasNext()) {
        List<StringBuilder> subtree = renderDirectoryTreeLines(iterator.next());
        if (iterator.hasNext()) {
            addSubtree(result, subtree);
        } else {
            addLastSubtree(result, subtree);
        }
    }
    return result;
}

private static void addSubtree(List<StringBuilder> result, List<StringBuilder> subtree) {
    Iterator<StringBuilder> iterator = subtree.iterator();
    //subtree generated by renderDirectoryTreeLines has at least one line which is tree.getData()
    result.add(iterator.next().insert(0, "├── "));
    while (iterator.hasNext()) {
        result.add(iterator.next().insert(0, "│   "));
    }
}

private static void addLastSubtree(List<StringBuilder> result, List<StringBuilder> subtree) {
    Iterator<StringBuilder> iterator = subtree.iterator();
    //subtree generated by renderDirectoryTreeLines has at least one line which is tree.getData()
    result.add(iterator.next().insert(0, "└── "));
    while (iterator.hasNext()) {
        result.add(iterator.next().insert(0, "    "));
    }
}

with this output:

DirectoryCatalog
├── .git
│   ├── COMMIT_EDITMSG
│   ├── config
│   ├── description
│   ├── HEAD
│   ├── hooks
│   │   ├── applypatch-msg.sample
│   │   ├── commit-msg.sample
│   │   ├── post-commit.sample
│   │   ├── post-receive.sample
│   │   ├── post-update.sample
│   │   ├── pre-applypatch.sample
│   │   ├── pre-commit.sample
│   │   ├── pre-push.sample
│   │   ├── pre-rebase.sample
│   │   ├── prepare-commit-msg.sample
│   │   └── update.sample
│   ├── index
│   ├── info
│   │   └── exclude
│   ├── logs
│   │   ├── HEAD
│   │   └── refs
│   │       ├── heads
│   │       │   └── master
│   │       └── remotes
│   │           └── origin
│   │               └── master
│   ├── objects
│   │   ├── 0b
│   │   │   └── b3fb0a15268c9770220938b1048305429527c7
│   │   ├── 0d
│   │   │   └── e508f20f1cb44ff543cec54ea93a71e5e40d1d
│   │   ├── 10
│   │   │   └── 9c753f3aab08f167f8409e6c9abec27cad6548
│   │   ├── 15
│   │   │   └── 7602556ebd120e656ae8dcd00cb361bfb3ef79
│   │   ├── 16
│   │   │   └── 952a5d1f5f3d15199f3e85b3d895a81990024e
│   │   ├── 1c
│   │   │   └── 5b36cd4d41b9b7d0df46d4184512098186c904
│   │   ├── 20
│   │   │   └── ae5cc82ebbb85f9161d8fd9783905e4cbee72c
│   │   ├── 21
│   │   │   └── e42add0fb2205a75ff621dbeb6d76455816b79
│   │   ├── 23
│   │   │   └── af4eaa4007ca941e562406b7b329c6ba4b395e
│   │   ├── 28
│   │   │   └── 6caf4b7be3ac85a476f3782220fe167a040971
│   │   ├── 2b
│   │   │   └── f6743fb97162e999fb6429510bb8a52114bc31
│   │   ├── 35
│   │   │   └── acd4ab6acb599d4e3244be2a8dc3a0161bcb3c
│   │   ├── 46
│   │   │   └── 1ef7c4db86e0466bb8f1f81dc25f12e3598db6
│   │   ├── 47
│   │   │   └── 4ce7f18330e5295ab1ef2eea66505235819e22
│   │   ├── 4b
│   │   │   └── 825dc642cb6eb9a060e54bf8d69288fbee4904
│   │   ├── 4e
│   │   │   └── 4e047c077c7825a845deebda7f97832cee847b
│   │   ├── 4f
│   │   │   └── 20b118269d71535e469966fdb5fe8a78ae6c9a
│   │   ├── 51
│   │   │   └── 677b295b4cd9931354dd52fb6050015d524fea
│   │   ├── 52
│   │   │   └── 9c34997d8262bd207037f0373703d68d4e1a4e
│   │   ├── 5b
│   │   │   └── 928f45816cc51609861f0930251accbe7de7f9
│   │   ├── 5d
│   │   │   └── 7cdbe029c6eff99c72d09b0a81347b605e77d7
│   │   ├── 61
│   │   │   └── 2b9d86f6ac365ede894e13a6273fd13833f44f
│   │   ├── 67
│   │   │   └── 2209cb240eac0303d6e3b6c7eb04242d661fad
│   │   ├── 6b
│   │   │   ├── c84e19913908f16141677b9d66abdb620350a0
│   │   │   └── d278b63be854ccd3c02b9038ee43366021b1a1
│   │   ├── 6c
│   │   │   └── 9d10e91679988caaee6759d48daf336f28a9a3
│   │   ├── 70
│   │   │   └── 4284c78f1c664c1348af5a784cca55c51fd66a
│   │   ├── 72
│   │   │   └── 1ab5fe4e4226930668048d97331103a92751be
│   │   ├── 78
│   │   │   └── 64a41eaf50f32ae8d2cab1acd200c405215c1a
│   │   ├── 82
│   │   │   └── 36f772feca12b3e301eea50774458a7e77c7fb
│   │   ├── 83
│   │   │   └── bc1e2a1f3187f28d63d7fa334744810d80c20d
│   │   ├── 87
│   │   │   └── 3ce97f624e9a1ae4a1bbf41218d50dc3503d6f
│   │   ├── 8a
│   │   │   └── 0b282aa6885fb573c106b3551f7275c5f17e8e
│   │   ├── 91
│   │   │   └── a7e269e19dfc62e27137a0b57ef3e430cee4fd
│   │   ├── 94
│   │   │   ├── 065a39b0dd7ce05604b96aff84d984493553e2
│   │   │   └── 5cbc994fb2d251437e71edf3a6eb289c5836ec
│   │   ├── 95
│   │   │   └── f481326b62c9adff2a0dad47480e279adb518f
│   │   ├── 9e
│   │   │   └── 1f7de67de38e67479cb8e38ad92d6354838393
│   │   ├── a1
│   │   │   └── e385dff1fb08b7a45ea52af43b22d240f0adab
│   │   ├── a7
│   │   │   └── 8934a5a81d95a85b9c97a3e1c1429186feb83d
│   │   ├── ab
│   │   │   └── 855c3379bdb3e4a22605de58f3438148d6ffe7
│   │   ├── b7
│   │   │   └── 64eafa2ba4e7f8f52a4e96da61b3d77f262d16
│   │   ├── bd
│   │   │   └── 9374662b409bb364779212874e7cf611541c38
│   │   ├── c1
│   │   │   └── f858c163f9c8cb89a145a60e87c9e35c97fb93
│   │   ├── c3
│   │   │   └── 35d07a1078656646ca6e980b468b938106d357
│   │   ├── c5
│   │   │   └── ac562c59d6a0430fa0ccd1fa6318fa5d48604f
│   │   ├── c8
│   │   │   └── f3d9284a65afbff6640da7970664ee2134c85b
│   │   ├── c9
│   │   │   └── 7a8bdb9088d370da7e88784a7a093b971aa23a
│   │   ├── cc
│   │   │   └── a6a5141b614b5e351c7e5b6b677ef09a931786
│   │   ├── d1
│   │   │   └── 76229a9e1d0172f84d060904d171be51f9d0f6
│   │   ├── d3
│   │   │   ├── 2f0a1ba59a0c52d3acc62de1d624fb68423ee3
│   │   │   └── b9dfcb3216a2feab03b1ae96280e3c1c963953
│   │   ├── e0
│   │   │   └── 6d2081865a766a8668acc12878f98b27fc9ea0
│   │   ├── e5
│   │   │   └── 3106578cd8adcd085c5c63c05fc49d5a5a3dbb
│   │   ├── info
│   │   └── pack
│   └── refs
│       ├── heads
│       │   └── master
│       ├── remotes
│       │   └── origin
│       │       └── master
│       └── tags
├── .gitattributes
├── .gitignore
├── .gradle
│   └── 2.2.1
│       └── taskArtifacts
│           ├── cache.properties
│           ├── cache.properties.lock
│           ├── fileHashes.bin
│           ├── fileSnapshots.bin
│           ├── outputFileStates.bin
│           └── taskArtifacts.bin
├── .idea
│   ├── .name
│   ├── compiler.xml
│   ├── copyright
│   │   └── profiles_settings.xml
│   ├── encodings.xml
│   ├── gradle.xml
│   ├── libraries
│   │   ├── Gradle__commons_io_commons_io_2_4.xml
│   │   ├── Gradle__junit_junit_4_11.xml
│   │   └── Gradle__org_hamcrest_hamcrest_core_1_3.xml
│   ├── misc.xml
│   ├── modules.xml
│   ├── scopes
│   │   └── scope_settings.xml
│   ├── uiDesigner.xml
│   ├── vcs.xml
│   └── workspace.xml
├── app
│   ├── app.iml
│   ├── build
│   │   ├── classes
│   │   │   └── main
│   │   │       └── gq
│   │   │           └── baijie
│   │   │               └── catalog
│   │   │                   ├── controllor
│   │   │                   │   ├── FilesScanner$MyFileVisitor.class
│   │   │                   │   └── FilesScanner.class
│   │   │                   ├── entity
│   │   │                   │   └── FileInformation.class
│   │   │                   ├── Main.class
│   │   │                   └── util
│   │   │                       ├── FileAssert.class
│   │   │                       ├── Hash.class
│   │   │                       ├── HEX.class
│   │   │                       ├── Printer$1.class
│   │   │                       ├── Printer$DirectoryTreeRender.class
│   │   │                       ├── Printer.class
│   │   │                       └── TreeNode.class
│   │   ├── dependency-cache
│   │   ├── resources
│   │   │   └── main
│   │   └── tmp
│   │       └── compileJava
│   ├── build.gradle
│   └── src
│       ├── main
│       │   └── java
│       │       └── gq
│       │           └── baijie
│       │               └── catalog
│       │                   ├── controllor
│       │                   │   └── FilesScanner.java
│       │                   ├── entity
│       │                   │   └── FileInformation.java
│       │                   ├── Main.java
│       │                   └── util
│       │                       ├── FileAssert.java
│       │                       ├── Hash.java
│       │                       ├── HEX.java
│       │                       ├── Printer.java
│       │                       └── TreeNode.java
│       └── test
│           └── java
├── DirectoryCatalog.iml
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── LICENSE
├── README.md
├── settings.gradle
└── temp
    ├── 150110161006.txt
    ├── 150110173453.txt
    ├── 150110175353.txt
    ├── 150111111311.txt
    ├── 150111112500.txt
    ├── 150111113411.txt
    ├── 150111155619.txt
    ├── 150111161958.txt
    ├── 150111162230.txt
    ├── 150111162632.txt
    ├── 150111163225.txt
    ├── 150111163330.txt
    ├── 150111164526.txt
    ├── 150111205412.txt
    ├── 150111210322.txt
    ├── 150111210506.txt
    ├── 150111210927.txt
    ├── 150111211249.txt
    ├── 150111211321.txt
    ├── 150111220750.txt
    ├── 150111220822.txt
    ├── 150111221437.txt
    ├── 150111221842.txt
    ├── 150111222437.txt
    ├── 150111234344.txt
    ├── 150111234433.txt
    └── 150112000034.txt
Community
  • 1
  • 1
BaiJie
  • 96
  • 1
  • 3
  • 1
    I don't really understand, where is the FileInformation class in TreeNode tree?? could you show the whole code? – givexa Aug 08 '21 at 08:11
5

You need to print out "|" whenever on the corresponding level you are not processing the last entry, but one of the entries before the last. You need to know this for every level separately, so you could add a bit mask or a string (say) as an extra argument to 'getInto'.

Antti Huima
  • 25,136
  • 3
  • 52
  • 71
5

Reference and modify fucntions of tree structures from this:

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

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

    public boolean isLeaf() {
        return children.size() == 0;
    }

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

    public int getLevel() {
        if (this.isRoot())
            return 0;
        else
            return parent.getLevel() + 1;
    }

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

    public TreeNode<T> findTreeNode(Comparable<T> cmp) {
        for (TreeNode<T> element : this.elementsIndex) {
            T elData = element.data;
            if (cmp.compareTo(elData) == 0)
                return element;
        }

        return null;
    }

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

    @Override
    public Iterator<TreeNode<T>> iterator() {
        TreeNodeIter<T> iter = new TreeNodeIter<T>(this);
        return 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);
    }


    public static String renderDirectoryTree(TreeNode<File> tree) {
        List<StringBuilder> lines = renderDirectoryTreeLines(tree);
        String newline = System.getProperty("line.separator");
        StringBuilder sb = new StringBuilder(lines.size() * 20);
        for (StringBuilder line : lines) {
            sb.append(line);
            sb.append(newline);
        }
        return sb.toString();
    }

    public static List<StringBuilder>
        renderDirectoryTreeLines(TreeNode<File>
                tree) {
            List<StringBuilder> result = new LinkedList<>();
            result.add(new StringBuilder().append(tree.data.getName()));
            Iterator<TreeNode<File>> iterator = tree.children.iterator();
            while (iterator.hasNext()) {
                List<StringBuilder> subtree =
                    renderDirectoryTreeLines(iterator.next());
                if (iterator.hasNext()) {
                    addSubtree(result, subtree);
                } else {
                    addLastSubtree(result, subtree);
                }
            }
            return result;
                }

    private static void addSubtree(List<StringBuilder> result,
            List<StringBuilder> subtree) {
        Iterator<StringBuilder> iterator = subtree.iterator();
        //subtree generated by renderDirectoryTreeLines has at least one
        line which is tree.getData()
            result.add(iterator.next().insert(0, "├── "));
        while (iterator.hasNext()) {
            result.add(iterator.next().insert(0, "│   "));
        }
    }

    private static void addLastSubtree(List<StringBuilder> result,
            List<StringBuilder> subtree) {
        Iterator<StringBuilder> iterator = subtree.iterator();
        //subtree generated by renderDirectoryTreeLines has at least
        one
            line which is tree.getData()
            result.add(iterator.next().insert(0, "└── "));
        while (iterator.hasNext()) {
            result.add(iterator.next().insert(0, "    "));
        }
    }

    public static void main(String[] args) {
        File file = new File("./");
        TreeNode<File> DirTree = createDirTree(file);
        String result = renderDirectoryTree(DirTree);
        System.out.println(result);
        try {
            File newTextFile = new File("./DirectoryTree.txt");

            FileWriter fw = new FileWriter(newTextFile);
            fw.write(result);
            fw.close();

        } catch (IOException iox) {
            iox.printStackTrace();
        }

    }
}

with this output:

.
├── .DS_Store
├── .idea
│   ├── compiler.xml
│   ├── dictionaries
│   │   └── yankai01.xml
│   ├── encodings.xml
│   ├── misc.xml
│   └── workspace.xml
├── data_exploring.iml
├── pom.xml
├── src
│   ├── .DS_Store
│   ├── main
│   │   ├── .DS_Store
│   │   ├── java
│   │   │   ├── FileAssert.java
│   │   │   ├── HttpUtils.java
│   │   │   ├── QuerySaveToCsv.java
│   │   │   ├── SampleData.java
│   │   │   ├── SampleIterating.java
│   │   │   ├── SampleSearching.java
│   │   │   ├── TreeNode.java
│   │   │   └── TreeNodeIter.java
│   │   └── resources
│   └── test
│       └── java
└── target
    ├── classes
    │   ├── FileAssert.class
    │   ├── HttpUtils.class
    │   ├── QuerySaveToCsv.class
    │   ├── SampleData.class
    │   ├── SampleIterating.class
    │   ├── SampleSearching$1.class
    │   ├── SampleSearching.class
    │   ├── TreeNode.class
    │   ├── TreeNodeIter$ProcessStages.class
    │   └── TreeNodeIter.class
    └── generated-sources
        └── annotations
atline
  • 28,355
  • 16
  • 77
  • 113
Medium core
  • 51
  • 1
  • 2
  • For printing the tree, my free [text-tree](https://gitlab.com/barfuin/text-tree) library might help. – barfuin Jun 04 '20 at 15:24
3
import java.io.File;

public class MainEntry {
public static void main(String[] args) {
    walkin(new File("/home/user")); //Replace this with a suitable directory
}

/**
 * Recursive function to descend into the directory tree and find all the files 
  @param dir A file object defining the top directory
 **/
public static void walkin(File dir) {

    File listFile[] = dir.listFiles();
    if (listFile != null) {
        for (int i=0; i<listFile.length; i++) {
            if (listFile[i].isDirectory()) {
              System.out.println("|\t\t");  
              walkin(listFile[i]);
            } else {

                System.out.println("+---"+listFile[i].getName().toString());

            }
        }
    }
}

}

Will work fine..The Logic is correct

Priyanshu Jha
  • 575
  • 5
  • 11
2

This is My Code. its Work

package DIRS;

import java.io.File;

public class LISTDIR
{
    public static void main(String[] args)
    {
        String path = System.getProperty("user.dir")+File.separator;

        File file[] = new File(path).listFiles();

        for(int i = 0 ; i < file.length ; i++)
        {
            if(file[i].isDirectory())
            {
                System.out.println("->"+file[i].getName());
                new LISTDIR().listfiles(file[i],"--");
            }
            else
            {
                System.out.println("-> "+file[i].getName());
            }
        }
    }

    public void listfiles(File f,String sprtr)
    {
        File file[] = f.listFiles();
        for(int i = 0 ; i < file.length ; i++)
        {
            if(file[i].isDirectory())
            {
                System.out.println(sprtr+file[i].getName());

                new LISTDIR().listfiles(file[i],"--"+sprtr);
            }
            else
            {
                System.out.println(sprtr+file[i].getName());
            }
        }
    }
}
13hola
  • 170
  • 1
  • 12
1

Here's my solution based on @BaiJie answer but 3x faster. It also supports corner case when null is provided (there is no tree). It creates rows node by node using stack to keep information if all parent's children were already processed instead of updating list of StringBuilders multiple times.

Sample usage can be found in my project.

public class TreePrinter {
public static final String PARENT_PIPE = "│   ";
public static final String PARENT_EMPTY = "    ";

public static final String CHILD_POINTER = "├── ";
public static final String LAST_CHILD_POINTER = "└── ";

public static <T> String print(TreeNode<T> tree) {
    if(null == tree) {
        return "";
    }
    return print(tree, new StringBuilder(), new ArrayList<>(), System.lineSeparator()).toString();
}

private static <T> StringBuilder print(TreeNode<T> tree, StringBuilder sb, List<Boolean> hasUnprocessedChildren, String lineSeparator) {
    List<TreeNode<T>> children = tree.getChildren();

    sb.append(tree.getValue()).append(lineSeparator);

    for(int i = 0; i < children.size(); i++) {
        if(i == children.size() - 1) {
            addLastNode(sb, hasUnprocessedChildren);
            hasUnprocessedChildren.add(false);
        } else {
            addNode(sb, hasUnprocessedChildren);
            hasUnprocessedChildren.add(true);
        }

        sb = print(children.get(i), sb, hasUnprocessedChildren, lineSeparator);

        hasUnprocessedChildren.remove(hasUnprocessedChildren.size() - 1);
    }

    return sb;
}

private static void addNode(StringBuilder sb, List<Boolean> hasUnprocessedChildren) {
    for(boolean hasUnprocessedChild : hasUnprocessedChildren) {
        sb.append(hasUnprocessedChild ? PARENT_PIPE : PARENT_EMPTY);
    }
    sb.append(CHILD_POINTER);
}

private static void addLastNode(StringBuilder sb, List<Boolean> hasUnprocessedChildren) {
    for(boolean hasUnprocessedChild : hasUnprocessedChildren) {
        sb.append(hasUnprocessedChild ? PARENT_PIPE : PARENT_EMPTY);
    }
    sb.append(LAST_CHILD_POINTER);
}
}
Harry
  • 144
  • 2
  • 9
0

Think of it like this -

procedure printOutput(file, depth):
    print "|   " depth times;
    print "+---" + file name;
    print new line
    if(file is a directory):
        for(each file inside file, say innerFile):
            call printOutput(innerFile, depth + 1);

Hope that helps.

Hari Menon
  • 33,649
  • 14
  • 85
  • 108
0
  import java.io.File;

  public class Tree
  {
    public static void main(String[] args) throws Exception
    {
      File folder = new File((args.length >= 1 && args[0].length() > 0)
        ? args[0]
        : ".");

      if (!folder.isDirectory())
      {
        throw new IllegalArgumentException("Invalid directory: " + folder.getName());
      }

      int level = 0;
      System.out.println(renderFolder(folder, level, new StringBuilder(), false));
    }

    private static StringBuilder renderFolder(File folder, int level, StringBuilder sb, boolean isLast)
    {
      indent(sb, level, isLast).append("[D] ").append(folder.getName()).append("\n");

      File[] objects = folder.listFiles();

      for (int i = 0; i < objects.length; i++)
      {
        boolean last = ((i + 1) == objects.length);

        if (objects[i].isDirectory())
        {
          renderFolder(objects[i], level + 1, sb, last);
        }
        else
        {
          renderFile(objects[i], level + 1, sb, last);
        }
      }

      return sb;
    }

    private static StringBuilder renderFile(File file, int level, StringBuilder sb, boolean isLast)
    {
      return indent(sb, level, isLast).append("--- ").append(file.getName()).append("\n");
    }

    private static StringBuilder indent(StringBuilder sb, int level, boolean isLast)
    {
      for (int i = 1; i < level; i++)
      {
        sb.append("|  ");
      }

      if (level > 0)
      {
        sb.append(isLast
          ? "`-"
          : "|-");
      }

      return sb;
    }

  }




  [D] .
  |-[D] classes
  |  |-[D] .data
  |  |  `---- Play.cdi_javac
  |  |---- ArrayListTest$Pair.class
  |  |---- ArrayListTest.class
  |  |---- ArrayTest.class
  |  |-[D] fruit
  |  |  |---- Apple.class
  |  |  `---- GrannySmith.class
  |  |---- IfTest.class
  |  |-[D] interview
  |  |  |---- Q1.class
  |  |  |---- Q2.class
  |  |  |---- Q3.class
  |  |  |---- Q3Sub.class
  |  |  |---- Q9Sub.class
  |  |  `---- Q9Super.class
  |  |---- IntOverflowTest.class
  |  |---- LinkedMapTest.class
  |  |-[D] log
  |  |  `---- Logger.class
  |  |---- log.properties
  |  |---- StringCaseTest.class
  |  |-[D] test
  |  |  |-[D] cache
  |  |  |  |-[D] test1
  |  |  |  |  |---- Cache.class
  |  |  |  |  |---- CacheEntry.class
  |  |  |  |  `---- RevisedCacheTest.class
  |  |  |  |-[D] test2
  |  |  |  |  |---- Cache.class
  |  |  |  |  |---- Log.class
  |  |  |  |  `---- RevisedCacheTest.class
  |  |  |  `-[D] test3
  |  |  |  |  |---- ConcurrentCache.class
  |  |  |  |  `---- ConcurrentCacheTest.class
  |  |  |---- Test.class
  |  |  `---- Test2.class
  |  |---- Test.class
  |  |---- Test2.class
  |  `---- ZipTest.class
  `---- Play.jpr
0

This is my solution:

import java.io.File;

public class MostrarArbol {

    public static void main(String args[]) {
        File carpeta = new File(args[0]);
        // File carpeta = new File(".");
        if (!carpeta.exists()) {
            System.out.println(args[0] + " NO existe.");
            return;
        }
        imprimeArbol(carpeta, "");
    }

    public static void imprimeArbol(File carpeta, String tabulador) {
        File contenido[] = carpeta.listFiles();
        if (contenido != null) {
            for (int i = 0; i < contenido.length; i++) 
                if (contenido[i].isDirectory()) {
                    System.out.println(tabulador + "|-" + contenido[i].getName());
                    imprimeArbol(contenido[i], tabulador + "|  ");
                } else {
                    System.out.println(tabulador + "+-" + contenido[i].getName().toString());
                }
        }
    }
}
pepino
  • 1
  • 1
    Nice one, would have been more helpfull if you would have named the variables and methods in english :) – John Doe May 19 '18 at 10:31
0

I was testing the solution with the most upticks written by @tan70 however it caused a null pointer exception on printing my home directory. I did some investigation and found that listFiles() can return null.

public File[] listFiles()

Returns an array of abstract pathnames denoting the files in the directory denoted by this abstract pathname.

If this abstract pathname does not denote a directory, then this method returns null. Otherwise an array of File objects is returned, one for each file or directory in the directory

/**
 * Pretty print the directory tree and its file names.
 *
 * @param path
 * @return
 */
public static String printDirectoryTree(String path) {
    File folder = new File(path);
    if (!folder.isDirectory()) {
        throw new IllegalArgumentException("folder is not a Directory");
    }
    int indent = 0;
    StringBuilder sb = new StringBuilder();
    printDirectoryTree(folder, indent, sb);
    return sb.toString();
}

private static void printDirectoryTree(File folder, int indent, StringBuilder sb) {

    if (folder != null && folder.isDirectory() && folder.listFiles() != null) {
        sb.append(getIndentString(indent));
        sb.append("+--");
        sb.append(folder.getName());
        sb.append("/");
        sb.append("\n");

        for (File file : folder.listFiles()) {
            if (file.isDirectory()) {
                printDirectoryTree(file, indent + 1, sb);
            } else {
                printFile(file, indent + 1, sb);
            }
        }
    }
}

private static void printFile(File file, int indent, StringBuilder sb) {
    sb.append(getIndentString(indent));
    sb.append("+--");
    if (file != null) {
        sb.append(file.getName());
    } else {
        sb.append("null file name");
    }
    sb.append("\n");
}

private static String getIndentString(int indent) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < indent; i++) {
        sb.append("|  ");
    }
    return sb.toString();
}
conteh
  • 1,544
  • 1
  • 17
  • 39