【问题标题】:list folders and files列出文件夹和文件
【发布时间】:2020-10-10 01:47:05
【问题描述】:

我使用此代码列出所有文件夹...

    public static void main(String[] args) throws Exception {
    File root = new File("C:\\Users\\resti\\Desktop\\example");
    if (!root.isDirectory())
    {
        System.out.println("some_text");
    }

    int level = 0;
        System.out.println(renderFolder(root, level, new StringBuilder(), false, new ArrayList<>()));

        }
    private static StringBuilder renderFolder(File folder, int level, StringBuilder sb, boolean isLast, List<Boolean> hierarchyTree) {
    indent(sb, level, isLast, hierarchyTree).append(folder.getName()).append("\n");

    File[] objects = folder.listFiles(new FilenameFilter() {
        @Override
        public boolean accept(File current, String name) {
            return new File(current, name).isDirectory();
        }
    });

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

        // this means if the current folder will still need to print subfolders at this level, if yes, then we need to continue print |
        hierarchyTree.add(i != objects.length - 1);
        renderFolder(objects[i], level + 1, sb, last, hierarchyTree);

        // pop the last value as we return from a lower level to a higher level
        hierarchyTree.remove(hierarchyTree.size() - 1);
    }
    return sb;
}


private static StringBuilder indent(StringBuilder sb, int level, boolean isLast, List<Boolean> hierarchyTree) {
    String indentContent = "\u2502   ";
    for (int i = 0; i < hierarchyTree.size() - 1; ++i) {
        // determines if we need to print | at this level to show the tree structure
        // i.e. if this folder has a sibling foler that is going to be printed later
        if (hierarchyTree.get(i)) {
            sb.append(indentContent);
        } else {
            sb.append("    "); // otherwise print empty space
        }
    }

    if (level > 0) {
        sb.append(isLast
                ? "\u2514\u2500\u2500"
                : "\u251c\u2500\u2500");
    }

    return sb;
}
}

它可以工作而且很酷,但问题是它不计算 .txt 或 .png 之类的普通文件...我知道它是在这个方法中写入的,但我知道如何在不破坏其他所有内容的情况下修复它

File[] objects = folder.listFiles(new FilenameFilter() {
        @Override
        public boolean accept(File current, String name) {
            return new File(current, name).isDirectory();
        }
    });

我可以重新制作方法或其他方式吗? (这段代码不是我的https://stackoverflow.com/a/33438475/13547682

【问题讨论】:

    标签: java list file directory


    【解决方案1】:

    假设我理解你的问题,这就是我的回答:

    在您给定的代码中:

    File[] objects = folder.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File current, String name) {
                return new File(current, name).isDirectory();
            }
    );
    

    您正在过滤文件夹中找到的所有文件,并使用 .isDirectory() 检查给定文件是否为目录。因此,生成的数组仅包含文件夹。

    如果您想要文件夹和文件作为结果,您可以删除过滤器,并且所有文件/文件夹都在给定文件夹中。

    File[] objects = folder.listFiles();
    

    因为代码现在还必须处理文件,所以我们必须更改一些处理缩进的代码。

    在更改文件和文件夹之前,代码将对对象数组中的每个元素执行相同的操作。但是现在我们要区分文件夹和文件。

    因此:

    private static StringBuilder renderFolder(File folder, int level, StringBuilder sb, boolean isLast, List<Boolean> hierarchyTree) {
        indent(sb, level, isLast, hierarchyTree).append(folder.getName()).append("\n");
    
        File[] objects = folder.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File current, String name) {
                return new File(current, name).isDirectory();
            }
        });
    
        for (int i = 0; i < objects.length; i++) {
            boolean last = ((i + 1) == objects.length);
    
            // this means if the current folder will still need to print subfolders at this level, if yes, then we need to continue print |
            hierarchyTree.add(i != objects.length - 1);
            renderFolder(objects[i], level + 1, sb, last, hierarchyTree);
    
            // pop the last value as we return from a lower level to a higher level
            hierarchyTree.remove(hierarchyTree.size() - 1);
        }
        return sb;
    }
    

    必须修改为如下所示:

    private static StringBuilder renderFolder(File folder, int level, StringBuilder sb, boolean isLast, List<Boolean> hierarchyTree) {
            indent(sb, level, isLast, hierarchyTree).append(folder.getName()).append("\n");
    
            File[] objects = folder.listFiles();
    
            for (int i = 0; i < objects.length; i++) {
                boolean last = ((i + 1) == objects.length);
                hierarchyTree.add(i != objects.length - 1);
                if (objects[i].isDirectory() == false) {
                    indent(sb, level, isLast, hierarchyTree).append(objects[i].getName()).append("\n");
                    hierarchyTree.remove(hierarchyTree.size() - 1);
                    continue;
                }
                // this means if the current folder will still need to print subfolders at this level, if yes, then we need to continue print |
                renderFolder(objects[i], level + 1, sb, last, hierarchyTree);
    
                // pop the last value as we return from a lower level to a higher level
                hierarchyTree.remove(hierarchyTree.size() - 1);
            }
            return sb;
    }
    

    重要的变化是,如果数组中的对象不是文件夹,则调用 indent 函数,然后继续循环,而不对当前文件对象调用 renderFolder。

    if (objects[i].isDirectory() == false) {
            indent(sb, level, isLast, hierarchyTree).append(objects[i].getName()).append("\n");
            hierarchyTree.remove(hierarchyTree.size() - 1);
            continue;
    }
    

    在我的测试文件夹上对其进行测试,结果如下:

    └──62476474
        ├──target
        │   ├──generated-sources
        │   │   └──annotations
        │   ├──classes
        │   │   ├──Main.class
        │   └──maven-status
        │       └──maven-compiler-plugin
        │           └──compile
        │               └──default-compile
        │                   └──inputFiles.lst
        │                   └──createdFiles.lst
        └──pom.xml
        └──src
            ├──test
            │   └──java
            └──main
                └──java
                    └──Main.java
    

    这是我的文件夹结构的准确表示。

    这应该可以解决您的问题。

    【讨论】:

      【解决方案2】:

      试试这个

      try {
          String[] command = { "/bin/sh", "-c", "cd /var; ls -l" };
          System.out.println("shell script command:");
          Stream.of(command).forEach(e -> System.out.println(e));
          Process process = Runtime.getRuntime().exec(command);
          StringBuilder stringBuilder = new StringBuilder();
          BufferedReader reader = new BufferedReader(
                  new InputStreamReader(process.getInputStream()));
      
          String line = null;
          while ((line = reader.readLine()) != null) {
              System.out.println(line);
          }
      } catch (Exception e) {
          System.out.println("Error while executing: " + e);
      }
      

      【讨论】:

      • "/bin/sh", "-c", "cd /var; ls -l" 永远无法在 Windows 上运行,我认为在这里调用这样的外部程序确实是一种错误的方法
      【解决方案3】:

      您可以删除 FilenameFilter 并仅使用 listFiles()。如果在非目录File 上调用,它将返回目录中包含的所有文件和目录或null,因此在继续之前检查null 很重要。 renderFolder() 的重写可能是:

      private static StringBuilder renderFolder(File folder, int level, StringBuilder sb, boolean isLast, List<Boolean> hierarchyTree) {
              indent(sb, level, isLast, hierarchyTree).append(folder.getName()).append("\n");
      
              File[] objects = folder.listFiles();
      
              if (objects == null)
                      // not a directory, there is nothing to iterate over, return immediately 
                      return sb;
      
              for (int i = 0; i < objects.length; i++) {
                      boolean last = ((i + 1) == objects.length);
      
                      // this means if the current folder will still need to print subfolders at this level, if yes, then we need to continue print |
                      hierarchyTree.add(i != objects.length - 1);
                      renderFolder(objects[i], level + 1, sb, last, hierarchyTree);
      
                      // pop the last value as we return from a lower level to a higher level
                      hierarchyTree.remove(hierarchyTree.size() - 1);
              }
              return sb;
      }
      

      【讨论】:

        【解决方案4】:

        如果您的文件夹层次结构非常大,那么与从递归函数重复调用 File.list() 或 File.listFiles() 相比,NIO Files.walkFileTree 调用在生成目录树中所有文件的名称方面要快得多.

        但是您需要将代码的逻辑更改为 FileVisitor 的各种回调,因此除非您的速度太慢,否则不值得付出努力。见:

        Files.walkFileTree(dir, EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE, visitor);
        

        Files.walkFileTree(dir, visitor);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-05-06
          • 1970-01-01
          • 2018-08-06
          • 1970-01-01
          • 2012-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多