Форум: "Основная";
Текущий архив: 2004.03.28;
Скачать: [xml.tar.bz2];
Внизпо поводу FindFirst and FindNext... Найти похожие ветки
← →
mOOx_ © (2004-03-03 18:12) [0]Приветствую.
Проблема в том, что не могу задать Attr так, чтобы возвращались только каталоги. Как не кручусь, возвращается весь набор файлов.
Маску ставлю в *, а Attr в faAnyFile, а затем проверяю, faDirectory есть или нет. Так вот, мой алгоритм с такой логикой работать отказывается. Мне надо, чтоб в результате были только каталоги.
Мастера, я знаю, что Вы добрые и мне поможете. С меня кашаладка :)
PS. могет и пивка :)
← →
MBo © (2004-03-03 18:18) [1]В FAQ.
А проверяют наличие флага так:
if (Attr and faDirectory)>0
← →
pasha_golub © (2004-03-03 18:23) [2]А на код бы я взглянул. Что это за проверка такая? :-)
← →
mOOx_ © (2004-03-03 18:27) [3]Именно так я и проверяю! Проблема вот в чем: есть каталог 111 и есть файл 111.par. Таких каталогов штук 20 (с файлами соответственно) + еще файлов в этой директории полно (около 800). Так вот, если мне нужны только каталоги, то процесс просмотра немного затягивается. Может можно сделать, чтоб сначала искались каталоги, а затем шли файлы? Понятно расписал?
← →
mOOx_ © (2004-03-03 18:34) [4]Даже не так (уже весь день копаюсь, сам запутался :) ): идет рекурсивный просмотр папок начиная с корневой. В корне есть папки и пары (т.е. Count(Folders)=Count(.par)). В этих папках как раз и есть 800 файлов. Когда начинается просмотр папки 111 (пример) на предмет наличия в ней папок, то апликуха виснет. Так вот мне надо узнать, есть там папки или нет. Если нет, то и нефиг по такому массиву файлов бегать без надобности. Надо на другую итерацию переходить. Так вот как мне узнать, есть там папки кроме "." и ".."?
Вот теперь вроде яснее (и правельнее).
← →
TUser © (2004-03-03 18:35) [5]Вот как пишут в хелпе
if FindFirst(Edit1.Text, FileAttrs, sr) = 0 then
begin
repeat
if (sr.Attr and FileAttrs) = sr.Attr then
begin
RowCount := RowCount + 1;
Cells[1,RowCount-1] := sr.Name;
Cells[2,RowCount-1] := IntToStr(sr.Size);
end;
until FindNext(sr) <> 0;
FindClose(sr);
end;
В твоем случае вместо FileAttrs можно писать faDirectory
← →
MBo © (2004-03-03 18:36) [6]FAQ еще раз.
← →
mOOx_ © (2004-03-03 18:47) [7]В факах не то совсем.
А вот вызов FindFirst("txt",faDirectory) положительного результата все равно не дает :(
← →
savva © (2004-03-03 18:48) [8]сделай FindFirst("*.txt",faDirectory)
← →
savva © (2004-03-03 18:49) [9]стоп торможу - директорию ищещь? а чего путь не полный?
← →
mOOx_ © (2004-03-03 18:51) [10]да полное там все и правильное, только вот выдает он с таким параметром все равно все файлы
← →
mOOx_ © (2004-03-03 18:59) [11]Вообщем все вот как организовано
if Subdir then
begin
hFile:=FindFirst(Dir+"\*",faAnyFile,FFile);
if((hFile=0)and
((FFile.Attr and faDirectory) <> 0)and
(FFile.Name<>".")and
(FFile.Name<>".."))then
begin
if ExitLabel then
exit;
CheckFiles(Dir+"\"+FFile.Name,FileName);
end;
while(FindNext(FFile)=0)do
begin
if(((FFile.Attr and faDirectory) <> 0)and
(FFile.Name<>".")and
(FFile.Name<>".."))then
begin
if ExitLabel then
Exit;
CheckFiles(Dir+"\"+FFile.Name,FileName);
end;
end;
SysUtils.FindClose(FFile);
end;
Может, конечно, грубовато написано, но уж как умею :)
Так вот. Даже если я указываю faDirectory в FintFirst, то файлы все равно возвращаются. Я как-то не понимаю смысла параметра Attr.
← →
viajero (2004-03-03 19:13) [12]>Я как-то не понимаю смысла параметра Attr.
function FindFirst(const Path: string; Attr: Integer;
var F: TSearchRec): Integer;
const
faSpecial = faHidden or faSysFile or faVolumeID or faDirectory;
begin
F.ExcludeAttr := not Attr and faSpecial;
// Смысл такой:
// Если ты не укажешь faDirectory,
// то директории будут исключены из поиска.
// А обычные файлы будут найдены в любом случае
F.FindHandle := FindFirstFile(PChar(Path), F.FindData);
if F.FindHandle <> INVALID_HANDLE_VALUE then
begin
Result := FindMatchingFile(F);
if Result <> 0 then FindClose(F);
end else
Result := GetLastError;
end;
← →
Anatoly Podgoretsky © (2004-03-03 19:13) [13]mOOx_ © (03.03.04 18:12)
Нельзя и не пытайся.
← →
Юрий Зотов © (2004-03-03 19:17) [14]> mOOx_
Обычные файлы ищутся всегда, отключить их поиск нельзя. Смысл параметра Attr в том, чтобы задать поиск чего-то еще, кроме обычных файлов (если задать Attr=0, то будут искаться только обычные файлы).
Вам нужно первоначально задать faDirectory, а потом проверять ручками, с помощью if и and. И рассмотрите вот такую структуру кода, она проще, короче и надежнее:
procedure ScanDir(Dir: string);
var
SR: TSearchRec;
begin
Dir := IncludeTrailingBackslash(Dir);
if FindFirst(Dir + "*.*", faDirectrory, SR) = 0 then
try
repeat
if (SR.Attr = faDirectory)
and (SR.Name <> ".") and (SR.Name <> "..") then
begin
... // что-то делаем
ScanDir(Dir + SR.Name)
end
until FindNext(SR) <> 0
finally
FindClose(SR)
end
end;
← →
mOOx_ © (2004-03-03 19:18) [15]Спасибо большое за ответы. Больше не пытаюсь.
← →
Юрий Зотов © (2004-03-03 19:19) [16]Сорри, вот это неправильно:
if (SR.Attr = faDirectory)
Конечно, надо так:
if (SR.Attr and faDirectory <> 0)
← →
mOOx_ © (2004-03-03 19:24) [17]да, так на-а-а-амного красивше. Спасибо.
← →
viajero (2004-03-03 19:45) [18]Я лично пользуюсь простенькой обёрткой над FindFile/Next/Close:
unit FileIt;
interface
uses
SysUtils;
type
PSearchRec = ^TSearchRec;
IFindFileIterator = interface
["{FC595960-347D-11D8-9F00-0050BAF21D9F}"]
function SearchRec: PSearchRec;
function Done: Boolean;
procedure Next;
end;
function CreateFindFileIterator(const Path: string; Attr: Integer): IFindFileIterator;
{
Example:
// На мой взгляд, выглядит немного приятнее
with CreateFindFileIterator("c:\windows\*.*", faDirectory) do
while not Done do
begin
if (SearchRec^.Name <> ".")and
(SearchRec^.Name <> "..")and
(SearchRec^.Attr and faDirectory <> 0) then
ListBox.Items.Add(SearchRec^.Name);
Next;
end;
}
implementation
type
TFindFileIterator = class(TInterfacedObject, IFindFileIterator)
private
FSearchRec: TSearchRec;
FDone: Boolean;
public
constructor Create(const Path: string; Attr: Integer);
destructor Destroy; override;
function SearchRec: PSearchRec;
function Done: Boolean;
procedure Next;
end;
function CreateFindFileIterator(const Path: string; Attr: Integer): IFindFileIterator;
begin
Result := TFindFileIterator.Create(Path, Attr);
end;
{------------------------- TFindFileIterator ----------------------------------}
constructor TFindFileIterator.Create(const Path: string; Attr: Integer);
begin
FDone := FindFirst(Path, Attr, FSearchRec) <> 0;
end;
destructor TFindFileIterator.Destroy;
begin
FindClose(FSearchRec);
inherited;
end;
procedure TFindFileIterator.Next;
begin
FDone := FindNext(FSearchRec) <> 0;
end;
function TFindFileIterator.Done: Boolean;
begin
Result := FDone;
end;
function TFindFileIterator.SearchRec: PSearchRec;
begin
Result := @FSearchRec;
end;
end.
← →
icWasya © (2004-03-04 10:05) [19]вся фишка в том, что используется
hFile:=FindFirst(Dir+"\*",faAnyFile,FFile);
вместоhFile:=FindFirst(Dir+"\*.*",faAnyFile,FFile);
← →
KADAN © (2004-03-04 10:21) [20]TDirectoryListbox.ReadDirectoryNames (вкладка Win 3.1)
← →
YuRock © (2004-03-04 10:45) [21]Сравнивать надо (корректно) так:
if (SR.Attr and faDirectory) = faDirectory then
ShowMessage("Да, это директория!");
← →
Юрий Зотов © (2004-03-04 12:50) [22]> YuRock © (04.03.04 10:45) [21]
С учетом того, что faDirectory есть целая степень двойки, не кажется ли Вам, чтоif SR.Attr and faDirectory = faDirectory
иif SR.Attr and faDirectory <> 0
это одно и тоже?
За исключением того, что второе работает чуть-чуть быстрее...
← →
YuRock © (2004-03-04 13:01) [23]> Юрий Зотов © (04.03.04 12:50) [22]
В данном случае разницы, конечно, нет, но красивее всегда писать в общем стиле, а то иногда по-запарке можно будет написать <> 0, а затем искать ошибку.
← →
MBo © (2004-03-04 13:38) [24]Чудная ошибка, встреченная как-то в чате:
Почему не работает
Style:=GetWindowLong...
if (Style and SBS_HORZ)<>0 then (скроллбар горизонтальный)
(Причина: SBS_HORZ = 0;)
← →
YuRock © (2004-03-04 13:48) [25]Во-во!
← →
MBo © (2004-03-04 13:55) [26]>YuRock © (04.03.04 13:48) [25]
Угу, но все же faDirectory - "честный" флаг, и с ним сталкивался каждый, поэтому, полагаю, здесь вполне уместно и с нулем сравнить.
← →
panov © (2004-03-04 14:47) [27]Для более тонкого понимания:
В Delphi Heplp приводится пример кода для FindFirst:
if FindFirst(Edit1.Text, FileAttrs, sr) = 0 then
begin
repeat
if (sr.Attr and FileAttrs) = sr.Attr then
begin
RowCount := RowCount + 1;
Cells[1,RowCount-1] := sr.Name;
Cells[2,RowCount-1] := IntToStr(sr.Size);
end;
until FindNext(sr) <> 0;
FindClose(sr);
end;
Где ошибка в этом коде, кто ответит?
← →
Юрий Зотов © (2004-03-04 14:50) [28]> panov © (04.03.04 14:47) [27]
Здесь даже не одна, а две ошибки.
← →
panov © (2004-03-04 15:09) [29]>Юрий Зотов © (04.03.04 14:50) [28]
Ошибки, не каксающиеся сути вопроса о поиске файлов, рассматривать не будем-)
← →
Юрий Зотов © (2004-03-04 15:10) [30]> panov © (04.03.04 15:09) [29]
Они обе относятся.
← →
Skyle © (2004-03-05 06:34) [31]Я вижу только одну ошибку.
Здесьif (sr.Attr and FileAttrs) = sr.Attr then
а вторую как-то не очень..
И ещё вопрос до кучи : в хелпе каких дельфей такой example приведён? В 5-х немного другой...
← →
Kor@l © (2004-03-05 09:04) [32]Незнай как кто ищет а я обычно ищю так
findFirst("*..",afanyfile,sr)
и ставлю условие такое
if (sr.name=".") or (sr.name="..") then {не чего не делю}
else
{а теперь идут имена дерикторий}
вроде сколько не делал всё время работало.
← →
Anatoly Podgoretsky © (2004-03-05 09:11) [33]Kor@l © (05.03.04 09:04) [32]
Работоспособность {а теперь идут имена дерикторий} исключена.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.03.28;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.033 c