それで、ネットワークドライブでこれに出くわしました。痛い。17000以上のファイルを含むディレクトリがありました。ローカル ドライブでは、最終更新日を確認するのに 2 秒もかかりませんでした。ネットワーク ドライブでは 58 秒かかりました!!! もちろん、私のアプリはインタラクティブなアプリなので、いくつか不満がありました.
いくつかの調査の後、Windows Kernel32 findfirstfile/findnextfile/findclose を実行してプロセスを劇的に改善する JNI コードを実装することが可能であると判断しましたが、32 ビット バージョンと 64 ビット バージョンなどがありました。クロスプラットフォーム機能を失います。
ここで少し厄介なハックがありますが、私がやったことです。私のアプリは主に Windows で動作しますが、そのように制限したくなかったので、次のようにしました。Windows 上で動作しているかどうかを確認します。その場合は、ローカル ハードディスクを使用しているかどうかを確認してください。そうでない場合は、ハック的な方法を実行します。
大文字と小文字を区別せずにすべてを保存しました。'ABC' と 'abc' の両方のファイルを持つディレクトリを持つ可能性のある他の OS にとっては、おそらく良い考えではありません。これを気にする必要がある場合は、 new File("ABC") と new File("abc") を作成し、 equals メソッドを使用してそれらを比較することで決定できます。Windows のような大文字と小文字を区別しないファイル システムでは true を返しますが、UNIX システムでは false を返します。
少しハックかもしれませんが、ネットワークドライブでの所要時間は 58 秒から 1.6 秒に短縮されたので、ハックに耐えることができます。
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;