如何按字母顺序列出文件(File.listFiles)?

111

我有如下代码:

class ListPageXMLFiles implements FileFilter {

        @Override
        public boolean accept(File pathname) {
                DebugLog.i("ListPageXMLFiles", "pathname is " + pathname);

                String regex = ".*page_\\d{2}\\.xml";
                if(pathname.getAbsolutePath().matches(regex)) {
                        return true;
                }
                return false;
        }
}

public void loadPageTrees(String xml_dir_path) {
        ListPageXMLFiles filter_xml_files = new ListPageXMLFiles();
        File XMLDirectory = new File(xml_dir_path);
        for(File _xml_file : XMLDirectory.listFiles(filter_xml_files)) {
                loadPageTree(_xml_file);
        }
}

FileFilter 工作得很好,但 listFiles() 似乎按字母逆序列出文件。有没有快速的方法告诉 listFiles() 按字母顺序列出文件?


1
不要使用正则表达式,改用.endsWith(".xml") - Fred
4个回答

252
< p > 无论是否使用过滤器,listFiles 方法都不能保证任何顺序。 < /p > < p > 然而,它返回一个数组,您可以使用 Arrays.sort() 进行排序。 < /p >
File[] files = XMLDirectory.listFiles(filter_xml_files);
Arrays.sort(files);
for(File _xml_file : files) {
    ...
}

这段代码能够工作是因为File是一个可比较的类,默认情况下按字典序对路径名进行排序。如果您想要以不同的方式进行排序,可以定义自己的比较器。

如果您喜欢使用流的话:

一种更现代的方法如下。要按字母顺序打印给定目录中所有文件的名称,请执行以下操作:

Files.list(Paths.get(dirName)).sorted().forEach(System.out::println)

System.out::println替换为您想要使用文件名做的任何操作。如果您只想要以"xml"结尾的文件名,只需执行以下操作:

Files.list(Paths.get(dirName))
    .filter(s -> s.toString().endsWith(".xml"))
    .sorted()
    .forEach(System.out::println)

再次强调,将打印操作替换为您想要的任何处理操作。


这是一行漂亮的代码,但Arrays.sort()似乎返回void而不是Iterable。 我会稍微研究一下。 - Thunder Rabbit
3
@Thunder Rabbit,对不起!!非常抱歉,你是正确的。我应该进行测试。我已经编辑了我的回答。 - Ray Toal
在 Windows 上似乎正常工作,但在 Ubuntu 中,大写字母的文件夹会先出现。 - jmhostalet
5
这是我期望的工作方式。在Unicode中,大写字母排在小写字母之前。Unix文件名区分大小写,所以大写字母排在前面。如果你在Windows上使用不区分大小写的文件名,大写和小写名称将混合在一起。这完全是按预期的操作。如果您想在Unix上采用Windows的方式,请提供一个比较器给sort函数。 - Ray Toal

4

在Java 8中:

Arrays.sort(files, (a, b) -> a.getName().compareTo(b.getName()));

倒序:

Arrays.sort(files, (a, b) -> -a.getName().compareTo(b.getName()));

2
你也可以使用这段代码:Arrays.sort(fList, Comparator.comparing(File::getName)); - plaidshirt
1
请小心处理此代码。该代码是不确定性的,不能直接使用。 - Tony Schwartz
1
为什么不行,是谁的代码? - Elliptica

2

我认为前面的答案是做这件事情的最好方式,这里提供另一种简单的方法,只需打印排序后的结果。

 String path="/tmp";
 String[] dirListing = null;
 File dir = new File(path);
 dirListing = dir.list();
 Arrays.sort(dirListing);
 System.out.println(Arrays.deepToString(dirListing));

请问您能否提供一下您认为这不是正确答案的原因,这样我就可以相应地进行修正。 - grepit
1
我真的不明白将文件数组转换为字符串数组然后排序的优势,而不是像被接受的答案那样直接对文件数组进行排序。 - zelanix
@zelanix 感谢您提供反馈。我并不是所有问题都有答案,有时回答问题时也会犯错。我已经更新了答案,请您再次查看并确认这是否是更好的解决方案。如果您能重新考虑一下您的投票,我将不胜感激。提前致谢。 - grepit
1
好的,现在你可以证明为什么如果你只想要打印结果的话就更简单,我会撤销我的反对票。 - zelanix
3
我认为使用list()而不是listFiles()会有优势,因为它只提供文件名而不包括父目录路径,这样字符串更短,排序和比较所需的CPU时间更少。 - Diljeet

0

这是我的代码:

        try {
            String folderPath = "../" + filePath.trim() + "/";
            logger.info("Path: " + folderPath);
            File folder = new File(folderPath);
            File[] listOfFiles = folder.listFiles();
            int length = listOfFiles.length;
            logger.info("So luong files: " + length);
            ArrayList<CdrFileBO> lstFile = new ArrayList< CdrFileBO>();

            if (listOfFiles != null && length > 0) {
                int count = 0;
                for (int i = 0; i < length; i++) {
                    if (listOfFiles[i].isFile()) {
                        lstFile.add(new CdrFileBO(listOfFiles[i]));
                    }
                }
                Collections.sort(lstFile);
                for (CdrFileBO bo : lstFile) {
                    //String newName = START_NAME + "_" + getSeq(SEQ_START) + "_" + DateSTR + ".s";
                    String newName = START_NAME + DateSTR + getSeq(SEQ_START) + ".DAT";
                    SEQ_START = SEQ_START + 1;
                    bo.getFile().renameTo(new File(folderPath + newName));
                    logger.info("newName: " + newName);
                    logger.info("Next file: " + getSeq(SEQ_START));
                }

            }
        } catch (Exception ex) {
            logger.error(ex);
            ex.printStackTrace();
        }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接