从路径列表中表示文件系统(文件/目录)的 Java 树
Posted
技术标签:
【中文标题】从路径列表中表示文件系统(文件/目录)的 Java 树【英文标题】:Java Tree to represent filesystem (files/dir) from list of paths 【发布时间】:2012-06-07 10:13:12 【问题描述】:我有一个这样的路径列表
/mnt/sdcard/folder1/a/b/file1
/mnt/sdcard/folder1/a/b/file2
/mnt/sdcard/folder1/a/b/file3
/mnt/sdcard/folder1/a/b/file4
/mnt/sdcard/folder1/a/b/file5
/mnt/sdcard/folder1/e/c/file6
/mnt/sdcard/folder2/d/file7
/mnt/sdcard/folder2/d/file8
/mnt/sdcard/file9
因此,从这个路径列表(Stings)中,我需要创建一个 Java 树结构,该结构将文件夹作为节点,将文件作为叶子(不会有空文件夹作为叶子)。
我认为我需要的是 add 方法,我将一个字符串(文件的路径)传递给他们,并将其添加到树中的正确位置,如果它们不存在则创建正确的节点(文件夹)
当我在节点和叶子列表上时,这个树结构需要我获取节点列表(但我认为这将是树的正常特征)
我将始终将字符串作为路径,而不是真正的文件或文件夹。 有什么东西可以使用或者有源代码可以开始吗?
非常感谢。
【问题讨论】:
“源代码开始?”见File Browser GUI。 另见: ***.com/questions/1005551/… 【参考方案1】:感谢您的所有回答。我做了我的工作实施。 我认为我需要对其进行改进,以便在向树结构添加元素时通过更多缓存更好地工作。
正如我所说,我需要的是一种结构,使我能够对 FS 进行“虚拟”表示。
MXMTree.java
public class MXMTree
MXMNode root;
MXMNode commonRoot;
public MXMTree( MXMNode root )
this.root = root;
commonRoot = null;
public void addElement( String elementValue )
String[] list = elementValue.split("/");
// latest element of the list is the filename.extrension
root.addElement(root.incrementalPath, list);
public void printTree()
//I move the tree common root to the current common root because I don't mind about initial folder
//that has only 1 child (and no leaf)
getCommonRoot();
commonRoot.printNode(0);
public MXMNode getCommonRoot()
if ( commonRoot != null)
return commonRoot;
else
MXMNode current = root;
while ( current.leafs.size() <= 0 )
current = current.childs.get(0);
commonRoot = current;
return commonRoot;
MXMNode.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MXMNode
List<MXMNode> childs;
List<MXMNode> leafs;
String data;
String incrementalPath;
public MXMNode( String nodeValue, String incrementalPath )
childs = new ArrayList<MXMNode>();
leafs = new ArrayList<MXMNode>();
data = nodeValue;
this. incrementalPath = incrementalPath;
public boolean isLeaf()
return childs.isEmpty() && leafs.isEmpty();
public void addElement(String currentPath, String[] list)
//Avoid first element that can be an empty string if you split a string that has a starting slash as /sd/card/
while( list[0] == null || list[0].equals("") )
list = Arrays.copyOfRange(list, 1, list.length);
MXMNode currentChild = new MXMNode(list[0], currentPath+"/"+list[0]);
if ( list.length == 1 )
leafs.add( currentChild );
return;
else
int index = childs.indexOf( currentChild );
if ( index == -1 )
childs.add( currentChild );
currentChild.addElement(currentChild.incrementalPath, Arrays.copyOfRange(list, 1, list.length));
else
MXMNode nextChild = childs.get(index);
nextChild.addElement(currentChild.incrementalPath, Arrays.copyOfRange(list, 1, list.length));
@Override
public boolean equals(Object obj)
MXMNode cmpObj = (MXMNode)obj;
return incrementalPath.equals( cmpObj.incrementalPath ) && data.equals( cmpObj.data );
public void printNode( int increment )
for (int i = 0; i < increment; i++)
System.out.print(" ");
System.out.println(incrementalPath + (isLeaf() ? " -> " + data : "") );
for( MXMNode n: childs)
n.printNode(increment+2);
for( MXMNode n: leafs)
n.printNode(increment+2);
@Override
public String toString()
return data;
Test.java 用于测试代码
public class Test
/**
* @param args
*/
public static void main(String[] args)
String slist[] = new String[]
"/mnt/sdcard/folder1/a/b/file1.file",
"/mnt/sdcard/folder1/a/b/file2.file",
"/mnt/sdcard/folder1/a/b/file3.file",
"/mnt/sdcard/folder1/a/b/file4.file",
"/mnt/sdcard/folder1/a/b/file5.file",
"/mnt/sdcard/folder1/e/c/file6.file",
"/mnt/sdcard/folder2/d/file7.file",
"/mnt/sdcard/folder2/d/file8.file",
"/mnt/sdcard/file9.file"
;
MXMTree tree = new MXMTree(new MXMNode("root", "root"));
for (String data : slist)
tree.addElement(data);
tree.printTree();
如果您对改进有一些好的建议,请告诉我:)
【讨论】:
我认为改进它的一个好方法是添加一种简单的方法来遍历树。除此之外,干得好【参考方案2】:我自己实现了挑战的解决方案,它是available as a GitHubGist。
我在 DirectoryNode 中表示文件系统层次结构的每个节点。辅助方法 createDirectoryTree(String[] filesystemList) 创建一个目录树。
这是使用示例,包含在GitHubGist 中。
final String[] list = new String[]
"/mnt/sdcard/folder1/a/b/file1.file",
"/mnt/sdcard/folder1/a/b/file2.file",
"/mnt/sdcard/folder1/a/b/file3.file",
"/mnt/sdcard/folder1/a/b/file4.file",
"/mnt/sdcard/folder1/a/b/file5.file",
"/mnt/sdcard/folder1/e/c/file6.file",
"/mnt/sdcard/folder2/d/file7.file",
"/mnt/sdcard/folder2/d/file8.file",
"/mnt/sdcard/file9.file"
;
final DirectoryNode directoryRootNode = createDirectoryTree(list);
System.out.println(directoryRootNode);
System.out.println - 输出是:
value='mnt', children=[value='sdcard', children=[value='folder1',
children=[value='a', children=[value='b', children=[value='file1.file',
children=[], value='file2.file', children=[], value='file3.file',
children=[], value='file4.file', children=[], value='file5.file',
children=[]]], value='e', children=[value='c',
children=[value='file6.file', children=[]]]],
value='folder2', children=[value='d', children=[value='file7.file',
children=[], value='file8.file', children=[]]],
value='file9.file', children=[]]]
【讨论】:
【参考方案3】:似乎您可以调整 Trie / Radix Trie 或 Binary Search Tree 以适应任何一种情况。您可以扩充 Trie 以将“文件夹”存储为内部节点(而不是像常规 Trie 中的字符),或者您可以扩充二叉搜索树以将“文件夹”存储为内部节点(只要它们实现可比较的接口)和“文件”作为叶节点。
我对这些结构的实现链接在上面的文本中。
【讨论】:
【参考方案4】:我建议阅读data structures,尤其是trees。在 Java 中,您可以通过创建具有对其他节点的引用的节点类来表示这些。例如:
public class Node
private Node[] children;
/* snip other fields */
public boolean isFile()
return children.count == 0;
显然,您可以随心所欲地存储节点引用 - 数组或集合将适用于非二叉树。
根据您的文件列表,您可以阅读这些文件并填充您的树结构。
【讨论】:
【参考方案5】:看看新的Java 7 - nio2 package。你所需要的就在里面。
【讨论】:
这很有用,但不会将文本路径列表作为输入,如果您真的想导航实际的文件系统,这很好。但就我而言,我想将我的虚拟文件系统(抽象数据库)缓存在一个 txt 文件中。以上是关于从路径列表中表示文件系统(文件/目录)的 Java 树的主要内容,如果未能解决你的问题,请参考以下文章
“InfoDictionary 版本”在信息属性列表(plist 文件)中表示啥?