文件及目录在编译器里经常会用到。大家可以想想下,我们用的IDE哪个没有各种格式的文件?
于是文件、目录查询便提出更高的要求,要快速找到是否存在。
对于这个其实也很简单,就是使用hash映射,将文件、目录名映射到一个缓冲区里,然后到缓冲区查找对应的HASH值即可。
FP有个全局变量:
var
DirCache : TDirectoryCache;
即代表目录的缓存,内部实现如下:
TDirectoryCache = class
private
FDirectories : TFPHashObjectList; //存放已经缓存过的目录列表
function GetDirectory(const ADir:TCmdStr):TCachedDirectory;
procedure TCachedDirectory.ForceUseCache;
begin
if not FCached then
begin
FCached:=True;
Reload; //由此将目录所有文件加入缓存里去
end;
end;
procedure TCachedDirectory.Reload;
var
dir : TSearchRec;
entry : PCachedDirectoryEntry;
begin
FreeDirectoryEntries;
DirectoryEntries.Clear;
if findfirst(IncludeTrailingPathDelimiter(Name)+AllFilesMask,faAnyFile or faDirectory,dir) = 0 then
begin
repeat
if ((dir.attr and faDirectory)<>faDirectory) or //将文件及非"."和".."目录加入到缓存里去
((dir.Name<>'.') and
(dir.Name<>'..')) then
begin
{ Force Archive bit so the attribute always has a value. This is needed
to be able to see the difference in the directoryentries lookup if a file
exists or not }
Dir.Attr:=Dir.Attr or faArchive;
if not(tf_files_case_sensitive in source_info.flags) then
if (tf_files_case_aware in source_info.flags) then
begin
new(entry);
entry^.RealName:=Dir.Name;
entry^.Attr:=Dir.Attr;
DirectoryEntries.Add(Lower(Dir.Name),entry)
end
else
DirectoryEntries.Add(Lower(Dir.Name),Pointer(Ptrint(Dir.Attr)))
else
DirectoryEntries.Add(Dir.Name,Pointer(Ptrint(Dir.Attr)));
end;
until findnext(dir) <> 0;
findclose(dir);
end;
end;