在Java中解压缩到TreeMap中

我的问题相对简单。 有没有人知道一个能够将压缩文件结构解压缩到Java的TreeMap(或类似的可迭代结构)的免费库(LGPL)?

重点是,我自己可以做到这一点,但我不想重新发明已经很好的骑行轮:)

提前致谢!


所以我的事情是,我有一个zip文件,包含多个文件和目录,可能包含更多文件。 我正在寻找的是一种方便的方法,如何将这个树结构提取到一个对象图中,无论它是否是一个TreeMap。 例如:一个HashMap : {'root' => 'HashMap : {'file1.png' => byte[] content}}

所以我的事情是,我有一个zip文件,包含多个文件和目录,可能包含更多文件。 我正在寻找的是一种方便的方法,如何将这个树结构提取到一个对象图中,无论它是否是一个TreeMap。 例如:一个HashMap:{‘root’,’HashMap:{‘file1.png’=> byte [] content}}

正如我前一段时间回答的另一个问题,Java API中没有单一的“树”数据结构(树形接口),因为每次使用都需要其他function。 例如,您提议的HashMap树无法以类型保存的方式实现 – 您需要在某处使用包装器对象。

我不知道在某个地方是否已经存在一个类似于zip文件的树状视图,但是(不)回答你的问题,但是一旦你定义了你想要的树界面,就很难创建。


所以,这是一个示例类,它可以完成你想要的(根据我的理解)。

 import java.io.*; import java.util.*; import java.util.zip.*; /** * A immutable wrapper around {@link ZipEntry} allowing * simple access of the childs of directory entries. */ public class ZipNode { private ZipNode parent; private Map children; private boolean directory; /** * the corresponding Zip entry. If null, this is the root entry. */ private ZipEntry entry; /** the ZipFile from where the nodes came. */ private ZipFile file; private ZipNode(ZipFile f, ZipEntry entry) { this.file = f; this.entry = entry; if(entry == null || entry.isDirectory()) { directory = true; children = new LinkedHashMap(); } else { directory = false; children = Collections.emptyMap(); } } /** * returns the last component of the name of * the entry, ie the file name. If this is a directory node, * the name ends with '/'. If this is the root node, the name * is simply "/". */ public String getName() { if(entry == null) return "/"; String longName = entry.getName(); return longName.substring(longName.lastIndexOf('/', longName.length()-2)+1); } /** * gets the corresponding ZipEntry to this node. * @return {@code null} if this is the root node (which has no * corresponding entry), else the corresponding ZipEntry. */ public ZipEntry getEntry() { return entry; } /** * Gets the ZipFile, from where this ZipNode came. */ public ZipFile getZipFile() { return file; } /** * returns true if this node is a directory node. */ public boolean isDirectory() { return directory; } /** * returns this node's parent node (null, if this is the root node). */ public ZipNode getParent() { return parent; } /** * returns an unmodifiable map of the children of this node, * mapping their relative names to the ZipNode objects. * (Names of subdirectories end with '/'.) * The map is empty if this node is not a directory node. */ public Map getChildren() { return Collections.unmodifiableMap(children); } /** * opens an InputStream on this ZipNode. This only works when * this is not a directory node, and only before the corresponding * ZipFile is closed. */ public InputStream openStream() throws IOException { return file.getInputStream(entry); } /** * a string representation of this ZipNode. */ public String toString() { return "ZipNode [" + entry.getName() + "] in [" + file.getName() + "]"; } /** * creates a ZipNode tree from a ZipFile * and returns the root node. * * The nodes' {@link #openStream()} methods are only usable until the * ZipFile is closed, but the structure information remains valid. */ public static ZipNode fromZipFile(ZipFile zf) { return new ZipFileReader(zf).process(); } /** * Helper class for {@link ZipNode#fromZipFile}. * It helps creating a tree of ZipNodes from a ZipFile. */ private static class ZipFileReader { /** * The file to be read. */ private ZipFile file; /** * The nodes collected so far. */ private Map collected; /** * our root node. */ private ZipNode root; /** * creates a new ZipFileReader from a ZipFile. */ ZipFileReader(ZipFile f) { this.file = f; this.collected = new HashMap(); collected.put("", root); root = new ZipNode(f, null); } /** * reads all entries, creates the corresponding Nodes and * returns the root node. */ ZipNode process() { for(Enumeration entries = file.entries(); entries.hasMoreElements(); ) { this.addEntry(entries.nextElement()); } return root; } /** * adds an entry to our tree. * * This may create a new ZipNode and then connects * it to its parent node. * @returns the ZipNode corresponding to the entry. */ private ZipNode addEntry(ZipEntry entry) { String name = entry.getName(); ZipNode node = collected.get(name); if(node != null) { // already in the map return node; } node = new ZipNode(file, entry); collected.put(name, node); this.findParent(node); return node; } /** * makes sure that the parent of a * node is in the collected-list as well, and this node is * registered as a child of it. * If necessary, the parent node is first created * and added to the tree. */ private void findParent(ZipNode node) { String nodeName = node.entry.getName(); int slashIndex = nodeName.lastIndexOf('/', nodeName.length()-2); if(slashIndex < 0) { // top-level-node connectParent(root, node, nodeName); return; } String parentName = nodeName.substring(0, slashIndex+1); ZipNode parent = addEntry(file.getEntry(parentName)); connectParent(parent, node, nodeName.substring(slashIndex+1)); } /** * connects a parent node with its child node. */ private void connectParent(ZipNode parent, ZipNode child, String childName) { child.parent = parent; parent.children.put(childName, child); } } // class ZipFileReader /** * test method. Give name of zip file as command line argument. */ public static void main(String[] params) throws IOException { if(params.length < 1) { System.err.println("Invocation: java ZipNode zipFile.zip"); return; } ZipFile file = new ZipFile(params[0]); ZipNode root = ZipNode.fromZipFile(file); file.close(); root.printTree("", " ", ""); } /** * prints a simple tree view of this ZipNode. */ private void printTree(String prefix, String self, String sub) { System.out.println(prefix + self + this.getName()); String subPrefix = prefix + sub; // the prefix strings for the next level. String nextSelf = " ├─ "; String nextSub = " │ "; Iterator iterator = this.getChildren().values().iterator(); while(iterator.hasNext()) { ZipNode child = iterator.next(); if(!iterator.hasNext() ) { // last item, without the "|" nextSelf = " ╰─ "; nextSub = " "; } child.printTree(subPrefix, nextSelf, nextSub); } } } 

它有一个主要的测试方法,我的一个jar文件的输出是这样的:

  / ├─ META-INF/ │ ╰─ MANIFEST.MF ╰─ de/ ╰─ fencing_game/ ├─ start/ │ ├─ Runner.class │ ├─ ServerMain$1.class │ ├─ ServerMain.class │ ╰─ package-info.class ├─ log/ │ ├─ Log$1.class │ ├─ Log.class │ ├─ LogImplClient.class │ ├─ Loggable.class │ ╰─ package-info.class ╰─ tools/ ╰─ load/ ├─ ServiceTools$1.class ├─ ServiceTools$2.class ├─ ServiceTools$3.class ├─ ServiceTools.class ╰─ TwoParentClassLoader.class 

(但是,你需要一个支持unicode的终端和System.out的Unicode编码。)

java.util.zip.ZipFile怎么样? 这听起来像一个非常微不足道的包装,应该做你想要的。

您可以使用java.util.ZipFile使用ZipFile,获取其内容并将当前内容转换为java.io.File并检查它是否为Dir,如果是,则在aslo中进行迭代,您可以将它们存储在TreeMap中。

 ZipFile myzip = new ZipFile (new File("pathToMyZipFile.zip")); Enumeration zipEnumerator = myzip.entries(); while(zipEnumerator.hasMoreElements()) { ZipENtry ze= zipEnumerator.nextElement(); if(ze.isDirectory()) { // recurse } else { // add it to treeMap } }