Есть много вопросов по работе в BP7, TMT (3.90), FPC (2.4.0.i386-win32) под WinXP: 1) верно ли, процедуры FindFirst и FindNext могут одновременно работать с несколькими директориями и даже с одной директорией через несколько указателей; 2) верно ли, что указатель поиска в директории определяется только записью файла SR (тип TSearchRec), но не директорией в которой она расположена, т.е. только по записи файла SR возможно непосредственно определить ее директорию и ее расположение в директории; 3) верно ли, что вызов FindNext(SR) возвращает в SR следующую запись (если она есть, если нет - SR неопределено или исходное значение?) в директории ее (исходной записи SR) расположения, а не в директории из последнего вызова процедуры FindFirst; 4) верно ли, что вызов FindClose(SR) прекращает поиск (работу с указателем) в директории расположения записи, а не в директории из последнего вызова процедуры FindFirst, поиск в других директориях не прекращается (непонятно, зачем вообще нужна эта процедура, если вся работа идет с данными из записи SR); - без выполнения данных взаимосвязанных утверждений рекурсивный поиск в директориях НЕВОЗМОЖЕН (по крайней мере, без создания списков их содержимого),
далее: 5) верно ли, что путь к директории в вызове процедуры FindFirst должен заканчиваться разделителем '\'; 6) возможна ли проверка существования файла, директории или лог. диска по его имени/полному_имени без использования процедур FindFirst и FindNext; 7) возможна ли работа с текущей директорией (получение абс. пути, изменение); 8) верно ли, что имена директорий SR.name в их записях SR из их наддиректорий не содержат разделителя '\'; 9) верно ли, что записи в любой не изменившейся директории при каждой ее обработке процедурами FindFirst и FindNext выдаются в одном и том же порядке (лексикографическом по именам?); 10) как обеспечить работу с длинными именами файлов (как вызвать Win под FPC); 11) верно ли, что поле Time в TSearchRec - это время создания файла (если нет, как узнать/изменить время создания), или это время его последнего изменения/открытия; 12) что представляют собой неизвестные компилятору типы полей записи SR файла в директории под Win: TFileName (=string ?), THandle, TWin32FindData, каким характеристикам файла они и Fill (тип array[1..21] of Byte) отвечают;
Win32 target type TSearchRec = record Fill : array[1..21] of Byte; Attr : Byte; Time : Longint; Size : Longint; Name : TFileName; ExcludeAttr : Longint; FindHandle : THandle; FindData : TWin32FindData end;
верно ли, что вызов FindNext(SR) возвращает в SR следующую запись (если она есть, если нет - SR неопределено или исходное значение?) в директории ее (исходной записи SR) расположения, а не в директории из последнего вызова процедуры FindFirst;
Это что тут написано, можно объяснить? Какая директория последнего вызова FindFirst? Какая директория "ее (исходной записи SR) расположения"? Ты о чем вообще?
(Dir1<>Dir2)
FindFirst(Dir1+mask1, Attr1, SR1); (* Dir1 - директория расположения записи SR1 *) FindFirst(Dir2+mask2, Attr2, SR2); (* Dir2 - директория расположения записи SR2 и директория последнего вызова FindFirst *) FindNext(SR1); FindClose(SR1) либо FindClose(SR2);
- FindNext(SR1) ищет следующую запись в директории Dir1 расположения записи SR1 или ищет в последней вызванной FindFirst директории Dir2 игнорируя значение SR1 ?; нужно ли вообще значение SR1 для поиска, или только для присвоения результата ?; -- ...присваивая следующую запись значению SR1, если она найдена, каковым делает значение SR1, если она не найдена: делает неопределенным, оставляет прежнее (возможно непроинициированное), каким угодно (в т.ч. ошибочным) ?; --- можно ли из значения SR получить указатель поиска в директории, используется ли это в FindNext(SR) ?; а получить маску и атрибуты поиска, и вообще отнести SR по ее имени к конкретному вызову поиска FindFirst(Dir+mask, Attr, SR) ? (ведь значение SR мы можем присвоить другой переменной SR0 и работать уже с ней: FindNext(SR0), FindClose(SR0) - как мы (т.е. программа) определим по имени SR0 к какому вызову поиска она относится? если поисков допускается несколько одновременно - разве что по значению SR0); Быть может следует говорить не о директории поиска, а о самом поиске, с конкретными параметрами: директория, маска имени файла, атрибуты (привязан он к конкретному имени SR, или определяется через значение SR - неясно);
Цитата(volvo)
Цитата(ddn)
верно ли, что вызов FindClose(SR) прекращает поиск (работу с указателем) в директории расположения записи, а не в директории из последнего вызова процедуры FindFirst, поиск в других директориях не прекращается (непонятно, зачем вообще нужна эта процедура, если вся работа идет с данными из записи SR);
Директория расположения записи - это что? Запись располагается в памяти, если что... Терминология твоя ошибочна, задай вопросы с нормальной терминологией. И напиши, наконец, кусок кода, в котором у тебя получается не то поведение, которого ты ожидаешь... Не заставляй других угадывать, как это делал ты...
Директория расположения записи файла SR - это директория, откуда она была прочитана процедурой FindFirst или FindNext (где расположен отвечающий SR файл); ---- прекращает ли вызов FindFirst(Dir2+mask2, Attr2, SR2) поиск в директории Dir1, сбрасывая его указатель ? (т.е. допустим только один поиск единовременно?); ----- прекращает ли аналогично вызов FindClose(SR1) поиск в директории Dir2, а вызов FindClose(SR2) поиск в директории Dir1 ?;
Цитата(volvo)
Ответ выделен:
Цитата((rtl.pdf стр 299))
FindClose frees any resources associated with the search record F. This call is needed to free any internal resources allocated by the FindFirst or FindNext calls.
FindClose(SR) освобождает любые ресурсы ВСЕХ поисков ? (зачем параметр SR ?); или все-таки в последнего поиска вызванного FindFirst, или поиска соответствующего значению SR ?; В хелпе TMT ее нет, а у FPC вообще нет хелпа. Где-то на форуме видел пример с FindClose.
Цитата(volvo)
Цитата("ddn")
что представляют собой неизвестные компилятору типы полей записи SR файла в директории под Win
Компилятору все прекрасно известно. Повторяю: эти функции используются не первый год, если что-то неизвестно - ошибку ищи у себя в коде, значит, неверно вызываешь... Телепаты с форума ушли...
Я имел в виду, что в хелпе их нет. Что до ошибки, то пока до этого дело не дошло. У меня написана программка, но отладчика нет, а почему не компилируется (TMT, FPC): может синтаксическая мелочь какая, а может и тип неизвестен (ведь TSearchRec еще правильно вызвать нужно) - непонятно. Вот на BP7 есть отладчик, но какой! Вот он писал, что тип TSearchRec неизвестен - ладно, описал его явно (в Dos-варианте), функции max и min тоже неизвестны - их можно смоделировать; uses Dos - Error 15: File not found (DOS.TPW). - ладно, обойдемся; но дальше он даже простые вещи перестал принимать, и я сделал совсем простую программу!
program cd (dir1, dir2: string); begin dir1=dir2 end.
все равно выдает Error 89: ')' expected. (курсор на ':'), притом еще недавно на ту же самую программу выдавал что-то ... ':=' ... (курсор на '='). Ну как тут быть?! Странный отладчик и странный компилятор. Поэтому, я пока пытаюсь выяснить, как там в теории должно действовать (может я вообще неправильно что-то понимаю), чтобы не блуждать впотьмах, гадая, где там ошибка может быть.
Цитата(volvo)
То, чаво на белом свете, вообче не может быть! (по крайней мере - по твоему утверждению).
Я видел этот пример. Хотя я стараюсь не использовать рекурсию, стараюсь сделать стек через file или array. Эта же рекурсия меня насторожила, она усилила мои подозрения, что допустим только один поиск единовременно.
Цитата(volvo)
{$TELEPATHY ON} P.P.S. Разницу между локальными и глобальными переменными хорошо понимаешь? Корень твоей проблемы - в этом... {$TELEPATHY OFF}
Насчет проблемы с компиляцией - незнаю, а вот насчет проблем с пониманием работы FindFirst и FindNext - да. Да, я тоже тогда подумал про какие-то странные грязные трюки с глобальными переменными (в данном случае это параметры поиска). Если в внутри одной процедуры, то только один поиск единовременно - неявная глобальная переменная инициируемая FindFirst, то в разных вызовах - своя переменная поиска, локальная. Разве значение глобальной переменной не передается из тела процедуры внутрь всех процедурных вызовов в ней?
Цитата(volvo)
Цитата(ddn)
без выполнения данных взаимосвязанных утверждений рекурсивный поиск в директориях НЕВОЗМОЖЕН (по крайней мере, без создания списков их содержимого)
А мужики-то не знают, и уже десятки лет используют рекурсивный поиск в папках/подпапках... Если ты чего-то не осилил, не надо говорить, что это невозможно... В общем, пример, как пытался - в студию... Больше я догадываться не собираюсь... Будет код - будет разговор.
Я имел ввиду, что невозможен, если допустим только один поиск единовременно. С компилятором Паскаля я только начинаю работать. До этого я программировал в Мапле - исполняемая среда символьных вычислений, эрзац Паскаля/Модулы без статической типизации. Но работа с файлами неустраивала меня, слишком невнятно сделана. Мне требуется ясная работа с файлами и без ограничений.
Что до программки, которую я пишу. Возникла потребность написать (на BP7, TMT, FPC под WinXP) процедуру для селективного копирования файлов и директорий (в том числе из вложенных директорий) из одной исходной директории в другую; структура директорий, а также атрибуты, имена, времена создания файлов и директорий сохраняются (содержимое файлов конечно тоже); селекция идет по атрибутам, имени, размеру, времени создания файла или директории. Хотелось бы узнать, что там может быть некорректно.
Код
(* под файлами понимаются в том числе и директории *) (* глубина директорий c полными путями dir1 и dir2 принимается равной 0; глубина директории = глубина расположения содержимых ею файлов, в том числе поддиректорий; глубина директории на единицу больше глубины содержащей ее директории (наддиректории), т.е. на единицу больше глубины ее собственного расположения; текущие директории - директории, обрабатываемые процедурами findfirst и findnext; *) procedure fullcopydir( dir1, dir2 : string; (* полные пути к существующим и не вложенным одна в другую директориям (т.е. пути вида '<LetterLogDisk>:\ ... \'), полное содержимое которых соответственно копируется и является результатом копирования *) prov : boolean; (* флаг необходимости проверки путей dir1 и dir2 на невложенность *) sel : function( attr : byte; time : longint; size : longint; name : string (* string[12] *) ) : boolean (* функция селекции на копирование для вложенных файлов, по некоторым полям их записи; поддиректории '.' и '..' игнорируются *) ); const maxh = 127; (* предел глубины расположения файлов *) type t = record b : boolean; (* флаги обнаружения требуемых селекцией файлов в текущих вложенных директориях, либо требуемости самих этих директорий *) ln : byte; (* длины полных путей к текущим вложенным директориям *) dir : string; (* относительные (от dir1) пути к текущим вложенным директориям *) sr : tsearchrec (* записи (в их наддиректориах) текущих вложенных директорий *) end; var e : boolean; i : byte; c : t; f, d : file; h : 0..maxh; (* глубина расположения непосредственно обрабатываемого файла *) b : boolean; (* флаг обнаружения требуемых файлов в директории расположения непосредственно обрабатываемого файла *) ln : byte; (* длина полного пути к директории расположения непосредственно обрабатываемого файла *) sr : tsearchrec; (* запись непосредственно обрабатываемого файла в директории его расположения *) r : file of t; begin if prov then begin ln := min(length(dir1), length(dir2)); i := 1; while i<=ln and dir1[i]=dir2[i] do i := i+1; if i>ln then halt('исходные директории вложены') end; h := 0; b := true; ln := max(length(dir1), length(dir2)); dir := dir1; e := findfirst(dir1+'*', anyfile, sr)=0; reset(r); while e do begin if (sr.attr and directory)=directory then (* запись файла отвечает директории *) if (sr.name='.') or (sr.name='..') then e := findnext(sr)=0; else (* приращение глубины, переход поиска в поддиректорию, создание ее копии без содержимого *) begin c.b := b; c.ln := ln; c.dir := dir; c.sr := sr; write(r, c); h := h+1; b := sel(sr.attr, sr.time, sr.size, sr.name); ln := ln+length(sr.name)+1; dir := dir+sr.name+'\'; createdir(dir2+dir); assign(g, dir2+dir); setftime(g, sr.time); setfattr(g, sr.attr); e := findfirst(dir1+dir+'*', anyfile, sr)=0 end else (* запись файла не отвечает директории *) begin if sel(sr.attr, sr.time, sr.size, sr.name) then (* копирование файла *) begin b := true; assign(f, dir1+dir+sr.name); assign(g, dir2+dir+sr.name); reset(f, 1); rewrite(g, 1); while not eof(f) do begin read(f, i); write(g, i) end; close(f); close(g); setftime(g, sr.time); setfattr(g, sr.attr) end; e := findnext(sr)=0 (* поиск следующей записи *) end; while (not e) and h>0 do (* возвращения из директорий до первой, где продолжение поиска результативно, либо достигнута исходная директория *) begin h := h-1; seek(r, h); read(r, c); seek(r, h); if not b then (* удаление скопированых пустых (без скопированных требуемых селекцией файлов) нетребуемых директорий *) begin b := c.b; assign(g, dir2+dir); erase(g) end; ln := c.ln; dir := c.dir; findclose(sr); sr := c.sr; e := findnext(sr)=0 end end; close(r) end.