So, I came across this on network drives. Painful. I had a directory with 17000 + files. It took less than 2 seconds on the local drive to check the last modified date. On a network drive, it took 58 seconds !!! Of course, my application is an interactive application, so I had some complaints.
After some research, I decided it would be possible to implement some JNI code to make Windows Kernel32 findfirstfile / findnextfile / findclose to greatly improve the process, but then I had a 32-bit and 64-bit version, etc. and then lose cross platform capabilities.
Although a bit of a nasty hack here is what I did. My application works mainly on Windows, but I did not want to limit it, so I did the following. Check if I work on windows. If yes, then see if I use a local hard drive. If not, we are going to make a hacker method.
I kept everything case insensitive. This is probably not a great idea for other operating systems that may have a directory with both "ABC" and "abc". If you need to do this, you can decide by creating a new file ("ABC") and a new file ("abc"), and then use the equals method to compare them. On case-insensitive file systems such as windows, it will return true, but on Unix systems it will return false.
Although this may be a bit hacky, the time spent on it lasted from 58 seconds to 1.6 seconds on a network drive, so I can live with a hack.
boolean useJaveDefaultMethod = true; if(System.getProperty("os.name").startsWith("Windows")) { File f2 = f.getParentFile(); while(true) { if(f2.getParentFile() == null) { String s = FileSystemView.getFileSystemView().getSystemTypeDescription(f2); if(FileSystemView.getFileSystemView().isDrive(f2) && "Local Disk".equalsIgnoreCase(s)) { useJaveDefaultMethod = true; } else { useJaveDefaultMethod = false; } break; } f2 = f2.getParentFile(); } } if(!useJaveDefaultMethod) { try { ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/C", "dir " + f.getParent()); pb.redirectErrorStream(true); Process process = pb.start(); InputStreamReader isr = new InputStreamReader(process.getInputStream()); BufferedReader br = new BufferedReader(isr); String line; DateFormat df = new SimpleDateFormat("dd-MMM-yy hh:mm a"); while((line = br.readLine()) != null) { try { Date filedate = df.parse(line); String filename = line.substring(38); dirCache.put(filename.toLowerCase(), filedate.getTime()); } catch(Exception ex) { } } process.waitFor(); Long filetime = dirCache.get(f.getName().toLowerCase()); if(filetime != null) return filetime; } catch(Exception Exception) { } }
source share