![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поиск файлов. [D7, XP]
Tek Noise © (2005-11-06 14:32:00)Здравствуйте! Нашёл на просторах форума код.
Он не работает, выдвёт ошибку "Runtime error 216 at 00403DF8".
Мне собственно нужно, что бы программа искала заданную дирректорию(можно и фаил), и результат записывала в фаил. с записью проблем нету, а вот с поиском, и записью данных в переменную... Подскажите, что в нижеприведенном коде исправить. Спасибо!
program flist;
{$APPTYPE CONSOLE}
uses
Windows;
procedure Output(const FileName : String);
var
p : PChar;
begin
p := PChar(FileName);
CharToOEM(p, p);
WriteLn(p);
end;
procedure AddTrailingBackslash(var Str : String);
begin
if not (Str[length(Str)] in ['/', '\']) then Str := Str + '\';
end;
procedure DoSearch(Directory : String; const SearchSubdirectories : Boolean);
var
fd : TWin32FindData;
h : Cardinal;
begin
AddTrailingBackslash(Directory);
Output('Поиск по директории: ' + Directory);
h := FindFirstFile(PChar(Directory + '*'), fd);
if (h <> INVALID_HANDLE_VALUE) then begin
repeat
if (fd.cFileName[0] <> '.') and (fd.cFileName <> '..') then
if ((fd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY) then begin
DoSearch(Directory + fd.cFileName, SearchSubdirectories);
end else
Output(fd.cFileName);
until (FindNextFile(h, fd) = FALSE);
end;
end;
begin
DoSearch(ParamStr(1), true);
ReadLn;
end.
Tek Noise (2005-11-07 01:25:00) [1]Всё, дальше наверное сам спарвлюсь.
Всем огромное спасибо за помошь! =)
Zeqfreed (2005-11-07 01:15:00) [2]sniknik © (07.11.05 1:07) [22]
> кстати там 1705 уже (1.7) есть.
Да я перепутал, у меня 1.7 beta 5:)
Вроде все устраивает, да и использую я его только для серфинга локальных фтп-серверов.
> получается только точные сравнения на = '.' или = '..'
> правильные
По-моему в самой первой книжке по Delphi, что я читал был пример и там это говорилось, поэтому я хорошо запомнил :)
> нужно теперь переделывать, искать где оно есть и
> переделывать... ;(.
Нда, не очень это наверно веселое занятие. Но лучше поздно :)
Джо © (07.11.05 01:13) [23]
У меня она, создает, могу записать на видео и прислать ))
Джо (2005-11-07 01:15:00) [3]
> [23] Джо © (07.11.05 01:13)
Прошу извинить за дезинформацию. Создает-таки.
Джо (2005-11-07 01:13:00) [4]Версия 1.70 beta 5 (build 1634) не создает такого безобразия.
sniknik (2005-11-07 01:07:00) [5]Zeqfreed © (07.11.05 00:23) [21]
круто! действительно так и есть.
скачал не утерпел ;)
http://farmanager.com/download.php?l=ru
кстати там 1705 уже (1.7) есть.
получается только точные сравнения на = '.' или = '..' правильные, больше ничем не отличаются, подумал может чтото дополнительное в параметрах есть. нифига, и в остальной структуре (там зарезервированные переменные есть) смотрел, никакой закономерности не увидел. в общем то как у меня сравнение делается, на первую точку, неправильное. нужно теперь переделывать, искать где оно есть и переделывать... ;(.
а я все в проводнике да в проводнике. думал он актуально ошибки выдает.
Zeqfreed (2005-11-07 00:23:00) [6]sniknik © (07.11.05 0:11) [20]
На полном серьезе :)
Версия 1.5 beta build 1634
Думаю, что FAR не единственная "шаманская" программа, которая так умеет ;)
sniknik (2005-11-07 00:11:00) [7]Tek Noise (06.11.05 23:52) [19]
например
if Pos('.jpg', cFileName) > 0 then...
это если "имееться ли в", т.е. подстрока в строке.
если это проверка расширения, то надо с ним и сравнивать (см. ExtractFileExt функцию).
еще тебе скорее всего понадобится AnsiUpperCase т.к. поиск обычно делают без учета регистра букв.
Zeqfreed © (06.11.05 23:51) [18]
> Специально проверял - FAR'ом спокойно создаются каталоги .* ;)
серьезно? если так и есть то надо будет мне поменять подход в сравнении каталогов, на всякий случай. (far у меня только на работе. кстати у тебя версия какая? может глюк версии)
Tek Noise (2005-11-06 23:52:00) [8]sniknik © (06.11.05 23:41) [17]
Ок, подскажи, как сделать проверку, имееться ли в fd.cFileName например ".jpg"?
Ну незнаю я как =(
Zeqfreed (2005-11-06 23:51:00) [9]sniknik © (06.11.05 23:41) [17]
> хотя, я так не пишу, с Continue гораздо проще и
> читабельнее код получается.
Дело привычки и "воспитания" :)
> убирается "лишний" (в этом случае) блок begin end?
Убирается он оптимизатором, а я просто написал так, как глазу приятней и привычней :)
> если FindFirstFile не вернул хендла то и закрывать
> нечего. так?
Сначала написал FindClose до end; но потом переместил ниже, не знаю каким инстинктам следовал :) "Виноват, исправлюсь" (С) :)
> кроме этих системных каталогов (текущий и выше) не
> могут. тоже имхо, но не совсем, также смутно помню
> гдето читал про это. ;) искать не буду, но у себя
> всегда на это закладываюсь (себе доверяю ;), и пока
> коллизий не было.
Специально проверял - FAR'ом спокойно создаются каталоги .* ;)
Ну а вообще уже пошёл треп по пустякам, думаю консенсус достигнут :)
sniknik (2005-11-06 23:41:00) [10]Tek Noise (06.11.05 22:22) [12]
> Непонимаю, по каким параметрам идёт поиск?
> Немогу найти, где указать, чтобы поиск к примерё шёл по имени дирректории/файла содержащие к примеру "delphi"?
для этого тебе надо взять этот пример за основу и написать свою программу поиска, где это условие (имя содержит к примеру "delphi"/маску) было бы реализовано. (немного осталось. практически одно условие (в паре мест) добавить ;), ну и параметр в процедуре)
> Он искал только в корневой дирректории %)
правильно. директории под эту маску не подошли... ни одна. искать всетаки надо по "*". и после сравнивать. либо разбивать процедуру поиска на 2 блока, директории и файлы отдельно.
Zeqfreed © (06.11.05 22:43) [14]
> ИМХО, все-таки стоит учитывать ситуацию, что имена папок (и, насколько я знаю, файлов тоже) теоретически могут
> начинаться с точки.
кроме этих системных каталогов (текущий и выше) не могут. тоже имхо, но не совсем, также смутно помню гдето читал про это. ;) искать не буду, но у себя всегда на это закладываюсь (себе доверяю ;), и пока коллизий не было.
> Немного переделал, теперь вроде все работает как надо: ...
;о))) ну хотя бы в едином стиле. ;) и эта... не считай придирками...
но пара замечаний (только в качестве образования)
1 если FindFirstFile не вернул хендла то и закрывать нечего. так?
2 опять begin end для одной команды, ну тут хотябы оправдано, с условием внутри, да, но глаз режет. я обычно избавляюсь от такого. т.е. если бы я писал этот код
if ((fd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY) then begin
if (String(fd.cFileName) <> '.') and (fd.cFileName <> '..') and (SearchSubdirectories) then
DoSearch(Directory + fd.cFileName, SearchSubdirectories);
end else
Output(Directory + fd.cFileName);
то написал бы так
if ((fd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> FILE_ATTRIBUTE_DIRECTORY)
then Output(Directory + fd.cFileName)
else if (String(fd.cFileName) <> '.') and (fd.cFileName <> '..') and (SearchSubdirectories)
then DoSearch(Directory + fd.cFileName, SearchSubdirectories);
не форматирование, смысл. ну чего стоит условие на обратное заменить если этим убирается "лишний" (в этом случае) блок begin end?
хотя, я так не пишу, с Continue гораздо проще и читабельнее код получается.
Tek Noise (2005-11-06 23:16:00) [11]Zeqfreed,
В тоём коде попытался поставить в
h := FindFirstFile(PChar(Directory + '*.jpg'), fd);
Он искал только в корневой дирректории %)
Спасибо кстатьи что подредактировал ;)
Tek Noise (2005-11-06 23:03:00) [12]Zeqfreed © (06.11.05 22:43) [14]
Да, я уже почти разобрался =)
Вот что получилось:
Нормально? =)
Вот только осталось 1.
Нужно сделать так, что бы программа перед выводом имени файла сверяла, если в fd.cFileName имееться ".jpg", то, выводить, если нету - игнорировать.
Подскажи, как сделать проверку? Спасибо =)
procedure DoSearch(Directory : String{; const SearchSubdirectories : Boolean});
var
fd :TWin32FindData;
h :Cardinal;
begin
AddTrailingBackslash(Directory);
Output('Search in dir: ' + Directory);
h := FindFirstFile(PChar(Directory + '*'), fd);
if (h <> INVALID_HANDLE_VALUE) then begin
repeat
if (fd.cFileName[0] <> '.') and (fd.cFileName <> '') then
if ((fd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY) then
begin
DoSearch(Directory + fd.cFileName{, true SearchSubdirectories});
end else
// if fd.cFileName = '*.jpg' then
Output(fd.cFileName);
until (FindNextFile(h, fd) = FALSE);
end;
end;
begin
DoSearch('G:'{,true});
writeln('Search complite...');
ReadLn;
end.
Zeqfreed (2005-11-06 22:43:00) [13]В общем мой код тоже неверно построен был относительно папок и файлов вида .* . Немного переделал, теперь вроде все работает как надо: опциональный поиск по подкаталогам, освобождение дескриптора и обработка папок/файлов вида .* . Прошу любить и жаловать :)
procedure DoSearch(Directory : String; const SearchSubdirectories : Boolean);
var
fd : TWin32FindData;
h : Cardinal;
begin
AddTrailingBackslash(Directory);
h := FindFirstFile(PChar(Directory + '*'), fd);
if (h <> INVALID_HANDLE_VALUE) then begin
repeat
if ((fd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY) then begin
if (String(fd.cFileName) <> '.') and (fd.cFileName <> '..') and (SearchSubdirectories) then
DoSearch(Directory + fd.cFileName, SearchSubdirectories);
end else
Output(Directory + fd.cFileName);
until (FindNextFile(h, fd) = FALSE);
end;
FindClose(h);
end;
sniknik © (06.11.05 21:47) [11]
ИМХО, все-таки стоит учитывать ситуацию, что имена папок (и, насколько я знаю, файлов тоже) теоретически могут начинаться с точки.
Tek Noise (06.11.05 22:22) [12]
Параметры задаются при запуске приложения, например в св-вах ярлыка пропиши в поле Target дополнительно папку в которой тебе нужно искать.
А вообще тебе же нужно скорее всего изменять эти параметры во время выполнения? Тогда тебе достаточно взять эти процедуры и передавать им необходимые параметры в программе.
Tek Noise (2005-11-06 22:30:00) [14]Чес слово, де вводить эти параметры? %)
Просто по дефолту прога напоминает простую команду dir %)
Спасибо! =)
Tek Noise (2005-11-06 22:22:00) [15]Непонимаю, по каким параметрам идёт поиск?
Немогу найти, где указать, чтобы поиск к примерё шёл по имени дирректории/файла содержащие к примеру "delphi"?
sniknik (2005-11-06 21:47:00) [16]> твой код её просто проигнорирует, не так ли?
попробуй.
логика немного другая но результат тотже, и первое сранение делает ненужным второе. вот поэтому и подумал ;) у тебя же и так и по другому сравнивается.
и потом не заметил, я это дело внутрь другого сравнения перенес, т.к. и "." и ".." и так каталоги, а каталоги реже встречаются чем файлы, и проверка на каталог в любом случае делается, т.е. по моему будет код немного быстрее (меньше сравнений, не будет каждый файл дополнительно проверять).
и кстати вот еще одна нестыковка, у тебя в после проверки на директорию одна команда в begin end заключена, да конечно есть и такой стиль ;) но всетаки логичнее если таким образом несколько команд обьеденяются. поэтому думал так и было но ты оттуда чтото удалил/перенес.
Zeqfreed (2005-11-06 21:21:00) [17]sniknik © (06.11.05 21:18) [9]
Хорошо, допустим файл винда запретит, а папку? твой код её просто проигнорирует, не так ли?
sniknik (2005-11-06 21:18:00) [18]> Но разве кто-то запрещает создать файл .blablabla?
винда должна запретить.
> "Отмазка" принимается?
сам так сам. я не настаиваю, да и не говорил, сказал, что похоже изза логических несостыковок.
Zeqfreed (2005-11-06 20:54:00) [19]Прошу прощения за опечатки, руки тряслись ;)
Zeqfreed (2005-11-06 20:51:00) [20]sniknik © (06.11.05 19:56) [6]
Ну что я могу сказать. Имеет ли смысл оправдываться и с пеной у рта доказывать что я сам написано этот код? :) (Особенно если учесть, что он получился не весть какого качества..)
Ну, по крайней мере напишу пару слов:
SubDirectories действительно здесь не используется, просто по началу когда писал код (специально отвечал на вопрос, т.е. код написан практически "на коленке", просто с проверкой работоспособности в "полевых условиях" (читать: с последующей отладкой) при объявлении процедуры ввел этот параметр, но потом никак не отразил его в теле процедуры, т.к. совсем запамятовал.
Насчет строки if (fd.cFileName[0] <> '.') and (fd.cFileName <> '..') then.
. - текущий каталог
.. - каталог уровнем выше
Но разве кто-то запрещает создать файл .blablabla? - Нет, поэтому проверка выглядит именно таким образом, а доступ к символу в строке через индекс осуществел для того, чтобы не приводить 'null-terminated' строку к типу String.
Разве я где-то нелогично мыслю?
Единственное где я допустил промах, как я считаю, так это то, что я забыл закрыть дескриптор.
"Отмазка" принимается?