0

I have the following method to retrieve the names of a logfiles produced by logback in a log directory. The first 9 lines determine the logging directory:

    private List<String> getLogFileNames() {
        List<String> logFileNames = new ArrayList<>();

        ch.qos.logback.classic.Logger rootLogger = ((ch.qos.logback.classic.Logger) LOGGER).getLoggerContext().getLogger("root");

        Path logDir;

        Appender<ILoggingEvent> appender = rootLogger.getAppender("file");
        if (appender == null) {
            logDir = Paths.get(System.getProperty("user.dir"), "../logs");
        } else {
           RollingFileAppender<?> rollingFileAppender = (RollingFileAppender<?>) appender;
           logDir = Paths.get(rollingFileAppender.getFile()).getParent();
       }

        try {
            Files.list(logDir).forEach(log -> logFileNames.add(log.toFile().getName()));
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }

        return logFileNames;
}

Sometimes the following exception is thrown: java.nio.file.FileSystemException: ... : Too many open files

I suspect the exception is thrown in the Files.list(logDir).forEach() statement. Somehow in this piece of code files are being opened but never closed. How should I solve this? Can I use a foreach statement or should I use something like:

try(Stream<Path> stream = Files.walk(logDir)) {
    // Code to extract the filename
}
catch(UncheckedIOException ex) {
    throw ex.getCause();
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Mark Smith
  • 487
  • 1
  • 3
  • 16

1 Answers1

1

Duplicate: Why does usage of java.nio.files.File::list is causing this breadth-first file traversal program to crash with the "Too many open files" error?

Consider using the Try With Resources Approach.

President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
IEE1394
  • 1,181
  • 13
  • 33
  • Thanks. Before I posted this question I studied the 'duplicate'. Just to be sure: may I conclude that I can not use a forEach approach and I always shoud use a try with resources approach since file are being opened and will be closed in the impliced finally block? – Mark Smith Jul 15 '19 at 22:25
  • @MarkSmith Of course you can use `forEach()`. Just use try-with-resources too. Like this: `try (Stream stream = Files.list(logDir)) { stream.forEach(/*node here*/); }` – Andreas Jul 15 '19 at 22:38