【问题标题】:Get files in a directory sorted by last modified? [duplicate]获取按上次修改排序的目录中的文件? [复制]
【发布时间】:2012-09-03 20:53:50
【问题描述】:

在具有新 I/O API 的 Java 7 中,是否有一种简单的方法可以按上次修改日期列出目录的内容?基本上我只需要获取最长时间未修改的文件(按最后修改的升序排序,取第一个文件名)。

【问题讨论】:

  • 为什么会被标记为重复?这个问题是关于 Java NIO 的。另一个问题与 Java NIO 无关。不是重复的。

标签: java java-7


【解决方案1】:

杰弗里的答案稍微“流式”变体,有些人可能会觉得更容易。发布以确保完整性。

try (DirectoryStream<Path> files = Files.newDirectoryStream(path)) {
    StreamSupport.stream(files.spliterator(), false)
        .sorted((o1, o2) -> {
            try {
                return Files.getLastModifiedTime(o1).compareTo(Files.getLastModifiedTime(o2));
            } catch (IOException ex) {
                ...
            }
        })
        .filter(file -> Files.isRegularFile(file))
        .forEach(file -> {
        });
}

【讨论】:

  • 为什么sortedfilter 之前?
  • @ok2c 非常好!然而,Call requires API level 24。 API
【解决方案2】:

没有真正的“简单方法”来做到这一点,但有可能:

List<Path> files = new ArrayList<>();
try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
    for(Path p : stream) {
        files.add(p);
    }
}

Collections.sort(files, new Comparator<Path>() {
    public int compare(Path o1, Path o2) {
        try {
            return Files.getLastModifiedTime(o1).compareTo(Files.getLastModifiedTime(o2));
        } catch (IOException e) {
            // handle exception
        }
    }
});

这将对文件中最早修改的文件进行排序。 DirectoryStreams 不会遍历子目录。

【讨论】:

  • 感谢您提供完整的解决方案。 File.listFiles() 可能会使您的代码更短:-)
  • @stefan.at.wpf 但是它不会按照您的要求使用 NIO2
  • 啊好吧,抱歉,没注意到。我不需要 NIO,我只是想知道 NIO 是否会提供一个简单的解决方案 ;-)
  • 请注意,lastModifiedTime 的精度可能不足以比较文件。例如,当复制一堆文件时,所有目标文件最终都将具有相同的 lastModifiedTime,因此无法按其对它们进行排序。发生这种情况是因为 lastModifiedTime 的精度通常只设置为秒,而不是毫秒。
  • Collections.sort(files, Comparator.comparingLong(File::lastModified));
【解决方案3】:

在目录的 File 对象上使用 listFiles()。将数组转换为数组列表。然后使用 Collections 类上的静态排序方法和自定义 Comparator 对它们进行排序,该 Comparator 使用 Files 上的 getTotalSpace() 方法。 编辑:使用 lastModified 而不是 getTotalSpace。

【讨论】:

    【解决方案4】:
    lastModified()
    

    返回此抽象路径名表示的文件的最后修改时间。

    Java 7 - IO API

    【讨论】:

    • 谢谢,但是在一个包含 100 个文件的目录中,我需要获取最旧的文件,只是想知道是否有比手动比较所有 lastModified 值更好的方法,例如仅传递一个排序选项,然后根据排序方向获取列表的第一个或最后一个条目。
    • 为了知道哪个文件是最新/最旧的,有必要遍历所有文件。这就是(据我所知)FileFilter 所做的。除了 jdevelop 的帖子中提到的(编辑:可能有很多方法可以实现这一点)之外,唯一的事情就是创建一个比较器,就像 File f = new File(""); Arrays.sort(f.listFiles(), new Comparator&lt;File&gt;() { public int compare(File o1, File o2) { return (int)(o1.lastModified() - o2.lastModified()); } }); return f[0];
    【解决方案5】:

    您可以使用http://docs.oracle.com/javase/1.5.0/docs/api/java/io/File.html#listFiles(java.io.FileFilter) 并提供http://docs.oracle.com/javase/1.5.0/docs/api/java/io/FileFilter.html

    然后比较 http://docs.oracle.com/javase/1.5.0/docs/api/java/io/File.html#lastModified() 就完成了

    如果您确实关心性能 - 那么只需从文件列表中取一个具有最大值/最小值的值,这将为您带来 O(n) 复杂度

    【讨论】:

      【解决方案6】:

      注意:此解决方案需要 Guava。

      Java IO/NIO API 提供对目录列表的低级访问,但没有完成任何处理,这留给调用者。 访问目录列表以进行进一步处理时,新的 Java7 NIO DirectoryStream 占用空间最小,例如排序。

      这是我的解决方案:从 DirectoryStream 读取文件并从流中构建一个(可选)有限大小的排序队列。从队列中返回最旧/最新的元素。

      private void listFilesOldestFirst(final File directory, final Integer maxNumberOfFiles) {
      
          final Builder<File> builder =
                  MinMaxPriorityQueue
                  .orderedBy(LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
          if( maxNumberOfFiles != null ) {
              builder.maximumSize(maxNumberOfFiles);
          }
      
          // queue with constant space, if maxNumberOfFiles is set, otherwise behaves like an unbound queue with an O(log n) penalty for insertion
          final MinMaxPriorityQueue<File> oldestFiles = builder.create();
      
          try(DirectoryStream<Path> stream = Files.newDirectoryStream(directory.toPath())) {
              for(final Path p : stream) {
                  oldestFiles.add(p.toFile());
              }
          } catch (final IOException e) {
              throw new RuntimeException(e);
          }
      
          final File[] fileArray = oldestFiles.toArray(new File[]{});
          Arrays.sort(fileArray, oldestFiles.comparator());
          // ... use fileArray
      
          final ArrayList<File> arrayList = Lists.newArrayList(oldestFiles);
          Collections.sort(arrayList, oldestFiles.comparator());
          // ... use arrayList
      
      }
      

      Guava MinMaxPriorityQueueFileComparator 需要这些依赖项:

          <dependency>
              <groupId>com.google.guava</groupId>
              <artifactId>guava</artifactId>
              <version>18.0</version>
          </dependency>
          <dependency>
              <groupId>commons-io</groupId>
              <artifactId>commons-io</artifactId>
              <version>2.4</version>
          </dependency>
      

      您可能还会发现 Files.newDirectoryStreamfilter 参数很有用:

          final Filter<Path> sampleFilter = new Filter<Path>() {
              @Override
              public boolean accept(final Path entry) throws IOException {
                  return true; // see commons-io -> FileFilterUtils
              }
          };
      
          ...
          Files.newDirectoryStream(directory.toPath(), sampleFilter)
      

      【讨论】:

        猜你喜欢
        • 2022-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多