用Java写一个输出纯文本的目录树

mac2024-08-17  61

之前在用HUI的模板时看他的目录结构时他给了一个纯文本格式的目录结构,像这样.

以前不是这样的,老版本好看多了,反正搞个截图吧.后面自己搞一些项目的目录结构时,都是手搓控制格式.后面没事自己整了个目录扫描工具类,后面再看目录的结构什么的就一目了然了.

直接上自己写的一个目录扫描工具类吧:

package com.gxlm.temp.tools; import java.io.File; import java.util.ArrayList; import java.util.List; import org.gxlm.core.util.CollectionUtil; import org.gxlm.core.util.FileUtil; import org.gxlm.core.util.IOUtil; import org.gxlm.core.util.Resource; import org.gxlm.core.util.StringUtil; /** * Description 类描述: <br/> * 目录树 * * @version 创建时间:2019年10月23日 上午10:10:16 */ public class DirecTree { // 空白分隔符 private static final String BLANK_SPLIT = " "; // 竖线分隔符 private static final String VERTICAL_BLANK_SPLIT = "│ "; // 节点符 private static final String NODE = "├──"; // 文件图标 private static final String FILE_ICON = "▶ ○ "; // 非空目录图标 private static final String DIREC_ICON = "▼ ◇ "; // 空目录图标 private static final String EMPTY_DIREC_ICON = "▶ ◇ "; // 文件节点 private static String FILE_NODE = NODE; // 非空目录节点 private static String DIREC_NODE = NODE; // 空目录节点 private static String EMPTY_DIREC_NODE = NODE; // 扫描目录 private File direc; /** * 目录树 * * @version 日期:2019年10月25日 * @param direc 扫描目录 */ public DirecTree(String direc) { this(direc, false); } /** * 目录树 * * @version 日期:2019年10月25日 * @param direc 扫描目录 * @param showIcon 是否显示区分文件目录图标 */ public DirecTree(String direc, boolean showIcon) { this(new File(direc), showIcon); } /** * 目录树 * * @version 日期:2019年10月25日 * @param direc 扫描目录 */ public DirecTree(File direc) { this(direc, false); } /** * 目录树 * * @version 日期:2019年10月25日 * @param direc 扫描目录 * @param showIcon 是否显示区分文件目录图标 */ public DirecTree(File direc, boolean showIcon) { this.direc = direc; if (showIcon) { FILE_NODE = NODE + FILE_ICON; DIREC_NODE = NODE + DIREC_ICON; EMPTY_DIREC_NODE = NODE + EMPTY_DIREC_ICON; } } /** * 绘制目录树 * * @version 日期:2019年10月25日 */ public void draw() { drawDirecTree(direc, "", false, 1, null, null); } /** * 绘制目录树 * * @version 日期:2019年10月25日 * @param outFile 绘制树保存文件 * @param limitLevel 限制绘制深度 * @param likeEclipse 按eclipse的包结构绘制目录树(目录下只有一个子目录,子目录不占用一个分支) */ public void draw(File outFile, Integer limitLevel, boolean likeEclipse) { StringBuilder builder = outFile == null ? null : new StringBuilder(); if (likeEclipse) { File parentFile = direc.getParentFile(); if (parentFile == null)// 根目录 drawDirecTreeLikeEclipse(direc, null, "", false, 1, limitLevel, builder); else drawDirecTreeLikeEclipse(direc, parentFile.getAbsolutePath(), "", false, 1, limitLevel, builder); } else { drawDirecTree(direc, "", false, 1, limitLevel, builder); } if (builder != null) IOUtil.writeText(builder.toString(), outFile, "UTF-8", true); } /** * 绘制目录树-以eclipse的package视图风格显示目录文件 * * @version 日期:2019年3月19日 * @param file * @param basePath * @param prefix 节点前缀 * @param hasNext file是否有兄弟file * @param level 目录树深度 * @param limitLevel 限定显示目录树深度上限 * @param builder */ private void drawDirecTreeLikeEclipse(File file, String basePath, String prefix, boolean hasNext, int level, Integer limitLevel, StringBuilder builder) { if (limitLevel != null && level > limitLevel.intValue()) return; // 根目录路径以"\"字符结尾,而普通目录不以"\"字符结尾,这里统一下都不以"\"字符 if (StringUtil.isNotBlank(basePath) && basePath.lastIndexOf(File.separatorChar) == basePath.length() - 1) basePath = basePath.substring(0, basePath.length() - 1); // 文件 if (file.isFile()) { String nodeInfo = prefix + FILE_NODE + file.getName() + "(" + FileUtil.formatFileSize(file.length()) + ")"; if (builder == null) System.out.println(nodeInfo); else builder.append(nodeInfo).append("\r\n"); return; } File[] fileArr = file.listFiles(); // 空目录 if (CollectionUtil.isEmpty(fileArr)) { String nodeInfo = prefix + EMPTY_DIREC_NODE; if (StringUtil.isBlank(basePath)) nodeInfo += file.getAbsolutePath().replace(File.separator, file.getParentFile() == null? "": "."); else nodeInfo += file.getAbsolutePath().substring(basePath.length() + 1).replace(File.separatorChar, '.'); if (builder == null) System.out.println(nodeInfo); else builder.append(nodeInfo).append("\r\n"); return; } // 目录下有且仅有一个子目录 if (fileArr.length == 1 && fileArr[0].isDirectory()) { File f = fileArr[0]; while (true) { File[] tempFileArr = f.listFiles(); if (CollectionUtil.isEmpty(tempFileArr) || tempFileArr.length > 1 || tempFileArr[0].isFile()) break; f = tempFileArr[0]; } drawDirecTreeLikeEclipse(f, basePath, prefix, hasNext, level + 1, limitLevel, builder); return; } // 打印当前目录 String nodeInfo = prefix + DIREC_NODE; if (StringUtil.isBlank(basePath)) nodeInfo += file.getAbsolutePath().replace(File.separator, file.getParentFile() == null? "": "."); else nodeInfo += file.getAbsolutePath().substring(basePath.length() + 1).replace(File.separatorChar, '.'); if (builder == null) System.out.println(nodeInfo); else builder.append(nodeInfo).append("\r\n"); // 子目录及文件 String p = prefix + (hasNext ? VERTICAL_BLANK_SPLIT : BLANK_SPLIT); List<File> direcList = new ArrayList<File>(); for (File item : fileArr) { if (item.isFile()) drawDirecTreeLikeEclipse(item, file.getAbsolutePath(), p, false, level + 1, limitLevel, builder); else direcList.add(item); } if (CollectionUtil.isEmpty(direcList)) return; for (int i = 0; i < direcList.size(); i++) drawDirecTreeLikeEclipse(direcList.get(i), file.getAbsolutePath(), p, i != direcList.size() - 1, level + 1, limitLevel, builder); } /** * 绘制目录树-每个目录均占用一个位置(即只有一个子目录的也要展开) * * @version 日期:2019年10月23日 * @param file * @param prefix 节点前缀 * @param hasNext file是否有兄弟file * @param level 目录树深度 * @param limitLevel 限定显示目录树深度上限 * @param builder */ private void drawDirecTree(File file, String prefix, boolean hasNext, int level, Integer limitLevel, StringBuilder builder) { if (limitLevel != null && level > limitLevel.intValue()) return; // 文件 if (file.isFile()) { String nodeInfo = prefix + FILE_NODE + file.getName() + "(" + FileUtil.formatFileSize(file.length()) + ")"; if (builder == null) System.out.println(nodeInfo); else builder.append(nodeInfo).append("\r\n"); return; } File[] fileArr = file.listFiles(); // 空目录 if (CollectionUtil.isEmpty(fileArr)) { String nodeInfo = prefix + EMPTY_DIREC_NODE + (file.getParentFile() == null? file.getPath().replace(File.separator, ""): file.getName()); if (builder == null) System.out.println(nodeInfo); else builder.append(nodeInfo).append("\r\n"); return; } // 打印当前目录 String nodeInfo = prefix + DIREC_NODE + (file.getParentFile() == null? file.getPath().replace(File.separator, ""): file.getName()); if (builder == null) System.out.println(nodeInfo); else builder.append(nodeInfo).append("\r\n"); // 递归打印子目录及文件 String p = prefix + (hasNext ? VERTICAL_BLANK_SPLIT : BLANK_SPLIT); List<File> direcList = new ArrayList<File>(); for (File item : fileArr) { if (item.isFile()) drawDirecTree(item, p, false, level + 1, limitLevel, builder); else direcList.add(item); } if (CollectionUtil.isEmpty(direcList)) return; for (int i = 0; i < direcList.size(); i++) drawDirecTree(direcList.get(i), p, i != direcList.size() - 1, level + 1, limitLevel, builder); } /** * 测试绘制目树 * * @version 日期:2019年10月23日 * @param args */ public static void main(String[] args) { // 目录树,所有目录均展开,不限定目录深度,结果输出到控制台上 //new DirecStruct("E:\\Recently").draw(); // 目录树,像eclipse展示包结构一样展示目录树,不限定目录深度,结果输出到控制台上 // new DirecStruct("E:\\Recently").draw(null, null, true); // 目录树,像eclipse展示包结构一样展示目录树,不限定目录深度,结果输出到桌面上 new DirecTree("F:\\").draw(new File(Resource.getDesktopPath() + File.separatorChar + "西数-F盘.txt"), null, false); } }

生成效果:

FileUtil.formatFileSize(file.length())是格式化文件大小单位,这里也给下

public static String formatFileSize(long fileSize) { if (fileSize < 1024) return fileSize + "Byte"; else if (fileSize < 1024 * 1024) return ((long) (fileSize / 1024.0 * 100)) / 100.0 + "KB"; else if (fileSize < 1024 * 1024 * 1024) return ((long) (fileSize / 1048576.0 * 100)) / 100.0 + "MB"; else return ((long) (fileSize / 1073741824.0 * 100)) / 100.0 + "GB"; }

 

最新回复(0)