如何按字母顺序File.listFiles?


95

我有如下代码:

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()似乎是以相反的字母顺序列出文件。有没有一种快速的方法可以告诉listFile()您按字母顺序列出文件?


1
不要使用正则表达式,.endsWith(".xml")而要使用。
2015年

Answers:


221

listFiles带有或不带有过滤器的方法不能保证任何顺序。

但是,它确实返回一个数组,您可以使用对其进行排序Arrays.sort()

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。我会戳一下。
雷兔

3
@雷兔,我的歉意!!很抱歉,您是对的。我应该测试一下。我编辑了答案。
雷·托尔

在Windows中,它似乎工作正常,但在Ubuntu中,带有大写字母的文件夹首先出现。
jmhostalet 2014年

5
这就是我期望它起作用的方式。在Unicode中,大写字母位于小写字母之前。Unix的文件名区分大小写,因此大写字母优先。如果在Windows上使用不区分大小写的文件名,则大写字母和小写字母名称将混合在一起。这完全符合预期。如果要在Unix上使用Windows,请提供一个比较器sort
雷·托尔

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 2013年

1
-1我真的不明白将文件数组转换为字符串数组然后进行排序的好处,而不是像接受的答案那样对文件数组进行排序。
zelanix 2014年

@zelanix感谢您提供反馈。我没有所有的答案,有时会在回答问题时犯错误。我已经更新了答案,请您对其进行审核,看看这是否是更好的解决方案。如果您可以重新考虑自己的投票,我将不胜感激。提前致谢。
grepit 2014年

1
好的,现在您可以证明为什么只想打印结果更简单,所以我将删除我的否决票。
zelanix 2014年

3
@ CPU100我相信通过使用list()而不是listFiles()可以提供仅具有文件名而没有父目录路径的优点,从而缩短了字符串,并减少了排序/比较的cpu时间。
Diljeet

1

在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

请注意这一点。此代码是不确定的,不应按原样使用。
托尼·施瓦茨

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();
        }

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.