So I ran across this on network drives. Painful. I had a directory with 17000+ files on it. On a local drive it took less than 2 seconds to check the last modified date. On a networked drive it took 58 seconds!!! Of course my app is an interactive app so I had some complaints.
After some research I decided that it would be possible to implement some JNI code to do the Windows Kernel32 findfirstfile/findnextfile/findclose to dramatically improve the process but then I had 32 and 64 bit version etc. ugh. and then lose the cross platform capabilities.
Although a bit of a nasty hack here is what I did. My app operates on windows mostly but I didn't want to restrict it to do so so I did the following. Check to see if I am operating on windows. If so then see if I am using a local hard disk. If not then we are going to do the hackish method.
I stored everything case insensitive. Probably not a great idea for other OS's that may have a directory with both files 'ABC' and 'abc'. If you need to care about this then you can decide by creating a new File("ABC") and new File("abc") and then using the equals method to compare them. On case insensitive file systems like windows it will return true but on unix systems it will return false.
Although it may be a little hackish the time it took went from 58 seconds to 1.6 seconds on a network drive so I can live with the 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)
{
}
}
// this is SO SLOW on a networked drive!
long lastModifiedDate = f.lastModified();
dirCache.put(f.getName().toLowerCase(), lastModifiedDate);
return lastModifiedDate;