Java: why does it take several seconds to check if a file exists on an inaccessible Windows drive?

Viewed 42

Checking for an existing file using any available method is usually very fast, but if the file path includes an inaccessible (network) drive, the check takes several seconds.

Checking for a non-existent drive is no problem ("R:" in the code sample), but checking a known drive that is no longer accessible ("S:" in the code sample) takes very long time.

Edit: this has a significant effect both when validating a list of recent files (multiply each inaccessible file by 2-4 seconds) and when opening the standard JFileChooser(), which can take 1-2 minutes with a few disconnected drives.

Questions:

  1. Is this a known problem?
  2. Is there a workaround?

Context: Java 11 or 17 on Windows 10 with an existing "C:" drive, a non-existent "R:" drive, and a network drive "S:" that is not accessible.

Sample code:

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;

public class FileSystemExperiment {

   private static final String[] FILES = {
      System.getProperty("user.home"), // home dir exists
      "/no/such/file",                 // missing file on current drive
      "C:\\no\\such\\file",            // missing file on existing drive
      "R:\\",                          // an unknown drive
      "S:\\",                          // a known but inaccessible drive
   };

   private static long started;

   private static void exists(String... pathStrings) {
      for (String pathString : pathStrings) {
         File file = new File(pathString);
         Path path = file.toPath();
         System.out.printf("%nFile '%s' ...%n", file);

         started = System.currentTimeMillis();
         time("file.exists()", file.exists());
         time("file.lastModified()>0", file.lastModified() > 0);
         time("Files.exists(path)", Files.exists(path));
         time("Files.readAttributes(path)", readAttributes(path) != null);
      }
   }

   private static void time(String msg, boolean exists) {
      System.out.printf("%-30s | %-5s | time=%s ms%n", msg, exists, System.currentTimeMillis() - started);
      started = System.currentTimeMillis();
   }

   private static BasicFileAttributes readAttributes(Path path) {
      try {
         return Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
      }
      catch (IOException e) {
         return null;
      }
   }

   public static void main(String[] args) {
      exists(FILES);
   }
}

Output:

File 'C:\Users\p2r' ...
file.exists()                  | true  | time=1 ms
file.lastModified()>=0         | true  | time=0 ms
Files.exists(path)             | true  | time=2 ms
Files.readAttributes(path)     | true  | time=0 ms

File '\no\such\file' ...
file.exists()                  | false | time=0 ms
file.lastModified()>=0         | false | time=0 ms
Files.exists(path)             | false | time=1 ms
Files.readAttributes(path)     | false | time=0 ms

File 'C:\no\such\file' ...
file.exists()                  | false | time=0 ms
file.lastModified()>=0         | false | time=0 ms
Files.exists(path)             | false | time=1 ms
Files.readAttributes(path)     | false | time=1 ms

File 'R:\' ...
file.exists()                  | false | time=0 ms
file.lastModified()>=0         | false | time=0 ms
Files.exists(path)             | false | time=0 ms
Files.readAttributes(path)     | false | time=0 ms

File 'S:\' ...
file.exists()                  | false | time=7802 ms
file.lastModified()>=0         | false | time=10067 ms
Files.exists(path)             | false | time=7171 ms
Files.readAttributes(path)     | false | time=10047 ms

0 Answers
Related