【问题标题】:Java finding latest file in directory from date in file nameJava从文件名中的日期查找目录中的最新文件
【发布时间】:2020-03-05 13:11:56
【问题描述】:

我有一个目录,可以在其中接收与模式 ABC_STOCK_List_YYYYMMDD_YYYYMMDD.csv 匹配的文件。 我正在用 java 编写一个计划服务,我需要检查文件是今天的日期,然后对该文件执行我的处理。

ABC_STOCK_List_20200220_20200220.csv
ABC_STOCK_List_20200219_20200219.csv
ABC_STOCK_List_20200218_20200218.csv
ABC_STOCK_List_20200217_20200217.csv

到目前为止我有这个:

private Optional<File> findLatestFile(final String dir) {
    return Stream.of(new File(dir).listFiles())
                 .filter(
                         file -> !file.isDirectory()
                                 && file.getName().startsWith(prefix)
                                 && file.getName().endsWith(".csv")
                                 && isTodaysFile(file)
                 )
                 .findFirst();

}

private boolean isTodaysFile(File file) {
    return false;
}

我需要isTodaysFile() 的帮助,应该检查后者YYYYMMDD 是今天的日期。它不仅应该依赖文件名中的日期,还应该依赖文件系统 createdmodified 时间,也应该是今天。

【问题讨论】:

    标签: java spring file file-io nio


    【解决方案1】:

    这是我解决这个问题的方法。首先,我创建了两个帮助函数,一个从文件名中检索结束日期,另一个检索文件系统modified 时间。我认为没有必要检查created 时间,因为创建时间总是小于或等于修改日期时间。

    获取文件名结束日期的函数:

    private LocalDate getEndDate(File file) {
        String fileName = file.getName();
        String fileNameWithoutExtension = fileName.substring(0, fileName.lastIndexOf("."));
        String[] fileNameChunks = fileNameWithoutExtension.split("_");
        String endDateAsString = fileNameChunks[fileNameChunks.length - 1];
    
        return LocalDate.parse(endDateAsString, DateTimeFormatter.ofPattern("yyyyMMdd"));
    }
    

    接下来,检索文件系统modified 日期的函数。为此,我使用Files#getLastModifiedTime 来检索modified 日期:

    private LocalDate getLastModifiedDate(File file, ZoneId zoneId) {
        try {
            return ZonedDateTime
                    .ofInstant(Files.getLastModifiedTime(file.toPath()).toInstant(), zoneId)
                    .toLocalDate();
        } catch (IOException e) {
            throw new RuntimeException("Could not read file attributes: " + file.getAbsolutePath());
        }
    }
    

    最后,它只是使用调用这些函数并执行验证:

    boolean isTodaysFile(File file) {
        Clock systemUTCClock = Clock.systemUTC();
        LocalDate localDateNow = LocalDate.now(systemUTCClock);
    
        LocalDate fileEndDate = getEndDate(file);
    
        // first check - validate that the file name's end date is today
        if (!fileEndDate.isEqual(localDateNow)) {
            return false;
        }
    
        LocalDate lastModifiedDate = getLastModifiedDate(file, systemUTCClock.getZone());
    
        // second check - validate that the modified that is today
        // no need to check the creation date, since creation date is always less or equal to the last modified date
        return lastModifiedDate.equals(localDateNow);
    }
    

    我正在使用 Clock.systemUTC() 并基于此实例化所有日期,以确保我们始终使用 UTC

    • LocalDate.now(systemUTCClock)
    • systemUTCClock.getZone()

    如果目录中的输入文件是:

    ABC_STOCK_List_20200220_20200220.csv
    ABC_STOCK_List_20200219_20200219.csv
    ABC_STOCK_List_20200218_20200218.csv
    ABC_STOCK_List_20200217_20200217.csv
    ABC_STOCK_List_20200305_20200305.csv
    

    在撰写本文时,当前日期为 03-05-2020。调用findLatestFile时的输出文件为:

    ABC_STOCK_List_20200217_20200305.csv
    

    注意事项:

    • 我没有对文件名格式进行任何验证。如果格式有问题,您在检索结束日期时可能会遇到一些错误。

    【讨论】:

    • Java Instants 使用 UTC 作为他们的时区。但LocalDate.now() 可能不会。那么我们是否需要通过使用带有相关区域 ID 的 ZonedDateTime 来对此进行调整?否则Instant.now()的日期可能与本地日期不符。
    • 感谢@andrewjames 的建议。我已更新函数以使用 ZonedDateTime 并将“UTC”作为区域 ID。
    • return ZonedDateTime.ofInstant(Files.getLastModifiedTime(file.toPath()) .toInstant(), zoneId) .toLocalDate(); ??
    • 然后返回return getLastModifiedDate(ZoneId.of("UTC"), file).equals(LocalDate.now()); ?
    • 嗯好的,我会尝试为这段代码写一些单元测试。
    猜你喜欢
    • 1970-01-01
    • 2013-04-01
    • 2021-01-12
    • 1970-01-01
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多