我必须打印目录树(如树命令),例如:
.
+---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
我尝试使用以下代码:
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);
}
}
}
我试过几个版本,但它仍然不起作用。这该怎么做?如果有什么条件?我知道很简单,但我不能这样做。
答案 0 :(得分:23)
这就是我做到的。
守则
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();
}
}
结果
+--folder1/
| +--a.txt
| +--folder2/
| | +--b1.txt
| | +--b2.txt
| | +--b3.txt
| | +--folder3/
| +--folder4/
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);
}
}
答案 1 :(得分:6)
这是我的解决方案:
(TreeNode
类是从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, " "));
}
}
使用此输出:
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
答案 2 :(得分:4)
你需要打印出来的“|”无论何时在相应的级别,您都不处理最后一个条目,而是最后一个条目之一。你需要分别知道每个级别的这个,所以你可以添加一个位掩码或一个字符串(比如说)作为'getInto'的额外参数。
答案 3 :(得分:1)
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());
}
}
}
}
}
工作正常......逻辑是正确的
答案 4 :(得分:1)
这是我的代码。它的工作
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());
}
}
}
}
答案 5 :(得分:0)
想想这样 -
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);
希望有所帮助。
答案 6 :(得分: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
答案 7 :(得分:0)
这是我的解决方案:
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());
}
}
}
}
答案 8 :(得分:0)
我正在使用@ tan70编写的最多更新标记测试该解决方案,但是它在打印主目录时导致了空指针异常。我进行了一些调查,发现listFiles()可以返回null。
公共文件[] listFiles()
返回一个抽象路径名数组,该数组表示此抽象路径名表示的目录中的文件。
如果此抽象路径名不表示目录,则此方法返回 null 。否则,将返回一个File对象数组,目录中的每个文件或目录一个
/**
* 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();
}
答案 9 :(得分:0)
从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();
}
}
}
具有以下输出:
.
├── .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