Вот пример кода до и после использования listFiles
и использования isDirectory
для обхода дерева каталогов (мой код использует общий обратный вызов, чтобы фактически что-то делать с каждым каталогом и файлом; если бы я кодировал C #, это делегат).
Как вы можете видеть, подход listFiles
на самом деле более компактен и легко понятен, а также немного быстрее на локальном диске (950 мс против 1000 мс) и на диске LAN (26 секунд, против 28 секунд), оба за 23 тысячи файлов.
Вполне возможно, что для удаленного подключенного диска ускорение может быть значительным, но я не могу проверить это с работы. Удивительно, но это ускорение составляет всего около 10% в Windows RAS VPN. к сетевому диску.
Новый код
static public int processDirectory(File dir, Callback cbk, FileSelector sel) {
dir=dir.getAbsoluteFile();
return _processDirectory(dir.getParentFile(),dir,new Callback.WithParams(cbk,2),sel);
}
static private int _processDirectory(File par, File fil, Callback.WithParams cbk, FileSelector sel) {
File[] ents=(sel==null ? fil.listFiles() : fil.listFiles(sel)); // listFiles returns null if fil is not a directory
int cnt=1;
if(ents!=null) {
cbk.invoke(fil,null);
for(int xa=0; xa<ents.length; xa++) { cnt+=_processDirectory(fil,ents[xa],cbk,sel); }
}
else {
cbk.invoke(par,fil); // par can never be null
}
return cnt;
}
Старый код
static public int oldProcessDirectory(File dir, Callback cbk, FileSelector sel) {
dir=dir.getAbsoluteFile();
return _processDirectory(dir,new Callback.WithParams(cbk,2),sel);
}
static private int _processDirectory(File dir, Callback.WithParams cbk, FileSelector sel) {
File[] ents=(sel==null ? dir.listFiles() : dir.listFiles(sel));
int cnt=1;
cbk.invoke(dir,null);
if(ents!=null) {
for(int xa=0; xa<ents.length; xa++) {
File ent=ents[xa];
if(!ent.isDirectory()) {
cbk.invoke(dir,ent);
ents[xa]=null;
cnt++;
}
}
for(int xa=0; xa<ents.length; xa++) {
File ent=ents[xa];
if(ent!=null) {
cnt+=_processDirectory(ent,cbk,sel);
}
}
}
return cnt;
}