Здравствуйте. Нужна помощь... Как открыть файл, не зная его имя (задан только каталог, где находится)... Заранее спасибо.
Altair
16.06.2004 19:55
Какие-то данные о файле все же нужны. Открыть его можно, в следующих случаях:
В заданном каталоге один файл
У файла уникальные атрибуты. (например у всех "архивный" а у этого "скрытый")
Файл отличается от остальных расширением (или отсутствием такого)
Известен размер файла.
Известно время создания файла
Можно открыть по очереди все файлы в каталоге
Во всех этих случаях надо использовать процедуру FindFirst и в некоторых случаях FindNext. Обе они находятся в модуле DOS. То есть для их использования, подключаем его:
Код
Uses Dos, {... другие модули}; {...}
Вызывается процедура следующим образом: в разделе переменных, надо описать переменную, с типом SearchRec Например:
Код
Uses DOS; {...}Var A: SearchRec; {... другие переменные}
Теперь в программе мы можем вызвать процедуру FindFirst:
Код
{...} Begin FindFirst('*.TXT',AnyFile,A); {...} end.
Поясняю: Мы ищем ПЕРВЫЙ файл с расширением TXT в текущем каталоге, который может иметь любые(AnyFile) атрибуты. Данные о файле (если он найден), помещаются в переменную A (она имеет тип SearchRec). Тип SearchRec имеет следующую структуру:
Код
Type SearchRec = Record Fill : Array [1..21] Of Byte; Attr : Byte; Time : Longint; Size : Longint; Name : Array [0..12] Of Char; End;
Если файл не найден, то в переменную DosError помещается код ошибки 18 (нет больше файлов). Если нам надо продолжить поиск (какие-то условия нас не устраивают), то мы вызываем процедуру FindNext ... Но для ее вызова уже не надо указывать тип искомых файлов( их маску и атрибуты). Процедура FindNext вызывается всегда только после FindFirst.
Теперь, когда нужный файл найден:
Код
{ связываем файловую переменную с именем этого файла } Assign (f,a.name); { и открываем его } Reset(f)
Примечание: Если файл текстовый, то открыть его таким образом можно только на чтение, или только на дозапись.
Unreal
16.06.2004 20:16
Большое спасибо... Кстати, у меня последний случай...
Altair
16.06.2004 21:00
Пожалуйста В вашем случае (перебор всех файлов) можно использовать (нужно т.е.) цикл:
Так стоп. Значит вы не правильно описали переменную A. Покажите весь код (или хотя-бы ту часть, где переменные описываются и модули подключаются.
Unreal
17.06.2004 14:28
Что там могло быть не правильно, я не осознал... Но к вечеру, прошу заметить, ЗАГРУЗИВ СВОЙ "НЕ РАБОТАЮЩИЙ" КОД, все прекрасно заработало...
Появился еще один вопрос, возможно ли открыть текстовой файл для продолжения записи, не стирая данные, как это делает ReWrite? И не прибегая к типизированным и нетипизированным файлам...
Код
Uses DOS; Type SearchRec = Record Fill:Array [1..21] of Byte; Attr:Byte; Time:Longint; Size:Longint; Name:Array [0..12] of Char; end; Var a:SearchRec; f:Text; n:Integer;
Begin FindFirst('*.TXT',AnyFile, a); Assign (f,a.name); Reset(f); ReadLn(f,n); WriteLn(n); end.
Добавлено (17.06.04 11:51): Да и еще... Какой командой табуляцию вызвать?...
Altair
17.06.2004 17:31
Так, я понял, что первая проблемма с несовместимостью типов разрешена. Эта ошибка могла быть по 3 причинам:
Вы находились в режиме отладки и надо было нажать RUN-> Program Reset
Надо было скомпилировать заново программу в память
неизвестная причина
Файл на дозапись можно открыть процедурой append(f). Процедуры для табуляции нет, но можно легко написать, просто записываем сначала нужное количество пробелов:
Код
var i:byte; f:text; {...} begin for i:=1 to нужное_колическтво_пробелов do write(f,' '); {...}
Не забываем, что writeln записывает в файл и переводит на новую строку, а write просто пишет. Я вообще никогда не пользуюсь writeln, а заменяю на альтернативную: write('dfdsfdgsdfgsgsdgsd',#13,#10); P.S. Кстати, это же оптимизация .... пойду куда надо сообщу!
Unreal
17.06.2004 20:01
Скорее третья причина... А каким образом в типизированном файле перейти на следующую строку?... А на счет табуляции, с пробелами не получится, выравнивать текст разной длины...
Altair
17.06.2004 20:16
Цитата
Скорее третья причина...
Естественно ... :p5:
Цитата
А каким образом в типизированном файле перейти на следующую строку?...
Ой, кошмар какой! В типизированных файлах нет строк! Там есть только элементы файла Тут два случая:
При записи, переход на следующий эл-т осуществляесть автоматически
При чтении, переход осуществляется процедурой seek(f,n), где f -файловая переменная, а n- номер элемента, на который надо перейти.
Цитата
А на счет табуляции, с пробелами не получится, выравнивать текст разной длины...
Стоп, стоп, стоп! Мы значит говорим о разных вещах. Табуляция - это отступ от левого края на n символов. А вы что под этим понимаете?
BlackShadow
17.06.2004 20:36
Табуляция, насколько я помню, Олег, это выравнивание под определённую длинну, а не отступ, тем более от какого-то конкретного края.
Altair
17.06.2004 20:53
Ага, понял ,это у меня ассоциация табуляции и клавиши TAB Хотя выравнивание ИМХО называется форматирование текста. Ну текст можно выравнить несколькими способами:
читаем из файла строку, если длинная, то остаток помещаем в буфер, потом читаем следующую, сразу в начало пишем из буфера, и проверяем длинну, ну и т.д (а если считываемая строка короткая, то добавляем пробелы)
Посимвольно перезаписываем файл, исключая символы управления (#13, #10), а потом, опять перезаписываем, только вставляя их куда надо.
Unreal
18.06.2004 19:13
Такой еще вопрос: Создан ЕХЕ файл, при запуске которого идет обработка текстовых файлов... Как сделать, чтобы программа обрабатывала всегда только те файлы, которые лежат в ее каталоге, при этом местоположение ЕХЕ файла меняется?. Т.е. кинули в любую папку - запустили - обработала те файлы которые лежат в этой папке...
Altair
18.06.2004 19:21
При связывании файла, надо не указывать полный путь к файлу, а только имя: т.е. не так: assign(f,'C:\windows\sss.txt'); А так: assign(f,'sss.txt'); --------- Процедуры FindFirst и FindNext ищут файл в текущем каталоге. Текущий каталог в программе - тот, в котором находиться эта прога.
Можно сменить текущий каталог процедурой CHDIR('каталог');
Unreal
18.06.2004 19:52
Хорошо, а почему она обрабатывает только 10 файлов? Когда в каталоге 31...
Добавлено (19.06.04 4:28): И еще... Где можно найти КОД процедупы READ?
Altair
19.06.2004 8:33
2 причины: 1. Вы их 10 одновременно открываете. (странно, тогда должно быть ограничение - 14 файлов ) 2. Другие файлы не подходят по условию поиска (FindFirst) может у остальных другое расширение или еще что.
А код выложить не можете?
Добавлено (19.06.04 4:39):
Цитата(Unreal)
Где можно найти КОД процедуры READ
Зачем??? Там-же чистый асм. Если хотите заменить на более скоростную, то используйте BlockRead, только файл уже используйте нетипизированный.
Unreal
19.06.2004 10:51
Есть ли процедура, с помощью которой текстовой файл можно открыть и для записи и для чтения, одновременно...?
Добавлено (19.06.04 8:37): И возможно ли, во время работы в текстовом файле, вернуть курсор в начало файла?
Altair
19.06.2004 17:33
Открыть текстовый файл одновременно для чтения и записи нельзя. У меня была программка для чтения файла в память, там с ним можно делать все что угодно, а потом снова записывать на диск, могу ее поискать если надо.
Цитата
И возможно ли, во время работы в текстовом файле, вернуть курсор в начало файла?
Нет, не возможно. В этом недостаток текстовых файлов.
Да, что-то я стормозил. (с кем не бывает) Если файл уже открыт, то он сначала закрывается, а затем вновь открывается. Текущая позиция указателя устанавливается на начало файла. А вот если надо на произвольные элемент переместить, то не выйдет с текстовыми.
BlackShadow
21.06.2004 17:04
Я бы тоже не был так уверен... Текстовый файл по сути своей запись типа TextRec (см. в "АЗЫ", я там о ней упоминал). Вот оттуда можно взять и вытянуть Handle файла (см. свой недавний вопрос), а затем уже дёргать указатель куда захочешь. Проблема только в том, что для установки на 30-ую строку придётся считать ещё 29 Но доступ к n-ному символу осуществляется моментом
Ладно, ладно - согласен, извращенец... Ну и что...
Altair
21.06.2004 17:13
Цитата
Ладно, ладно - согласен, извращенец... Ну и что...
Я бы так не сказал, это между прочим есть оптимизация, т.к. это будет быстрее, чем закрывать файл, открывать заново, и заводив переменную, отсчитывать на n элемент.
Кстати, а что будет, если текстовый файл описать как File of string? Надо попробовать ...
BlackShadow
21.06.2004 17:17
Попробуй, попробуй. Только не забывай, что String - переменная "непостоянного" размера, а File Of может описываться для типов "фиксированного размера". Даже, если у тебя
Код
MyRec=Record a:Integer; b:String End;
То File Of MyRec - не прокатит, а если
Код
MyRec=Record a:Integer; b:String[255] End;
то File Of MyRec пойдёт, но считываться каждый раз будет по 258 байт.
Altair
21.06.2004 17:29
Попробовал, не получилось. (дальше для тех, кому интересно)
Код
Var f:file of string; fn:string; n:longint; begin assign(f,'a'); rewrite(f); fn:='aaaaa'; write(f,fn); fn:='bbbbbbb'; write(f,fn); close(f); end.
Это запись файла. В результате в файле a, если его читать как текстовый, будет: aaaaa (потом до 256 символа пробелы), дальше: bbbbbbb И такая программа:
Код
Var f:file of string; fn:string; n:longint; begin readln(fn); assign(f,fn); reset(f); for n:=0 to filesize(f)-1 do begin seek(f,n); read(f,fn); writeln(fn); end; close(f); end.
Работать не будет (она ничего не выведет на экран). Этот факт доказывает, что в памяти под простую строку резервируется 256 байт!
APAL
21.06.2004 21:18
Может поиграться с "file of char;"?
Altair
23.06.2004 11:36
Попробовать можно ... Только потеряются особенности текстового ("строчность" )
BlackShadow
23.06.2004 14:55
Не так уж и сложно написать что-нибудь типа Function GetString(F:TCharFile):String):String...
Stream
24.06.2004 9:40
А вы в курсе, что в типизированном файле чтение происходит в тыщу раз медленнее, чем в техтовом...
Romtek
24.06.2004 12:28
Stream, обоснуй.
virt
24.06.2004 19:36
romtek ну конечно не в тысячу ,но так как типизированный файл имеет некую гипотетическую структуру ,то процедура чтения как-то её анализирует. если ты сам будешь считывать файл как символьный ,а потом решать что там к чему в нем и нет ли ошибки ,то получается что дольше.
BlackShadow
25.06.2004 15:56
Бред.
P@sh@
25.06.2004 19:50
точно бред, никакой проверки на корректность данных при типизированном чтении не происходит (имхо), а так как данные считываются блоками, будет еще быстрее, чем из текстового (там же каждый символ надо анализировать на конец строки)
впрочем, всякое может быть, я ни разу (!) в своей практике не использовал типизированные файловые переменные, только text (textfile в дельфе) для ведения всяческих логов и просто file для бинарного доступа
BlackShadow
25.06.2004 20:01
То же самое...
Altair
1.07.2004 16:37
Цитата
А вы в курсе, что в типизированном файле чтение происходит в тыщу раз медленнее, чем в техтовом...
Это бред! Если на то пошло, то наоборот, процедуры для текстовых файлов работают медленнее процедур для типизированных и не типизированных. Пример: EOF работает в 2 раза медленнее, чем FileSize( при правильном использовании).
BlackShadow
1.07.2004 16:41
EOF и FileSize - это 2 разные вещи. Пояни про что ты говоришь.
Altair
1.07.2004 17:00
Конечно разные, я к тому что если использовать текстовый файл, то для проверки конца обычно используеться EOF, а в типизированных используют текущую позицию в файле и проверяют равна ли она FileSize.
BlackShadow
1.07.2004 17:25
Oleg_Z прав. В общем случае EOF работает примерно так: 1) temp = FilePos; 2) size = Seek(end); 3) Seek(temp) 4) eof:=temp=size; Ну, фигурально выражаясь. Под DOS пункты 1..3 выполняются одной и той же функцией. Единственное на яём может произойти экономия времени - на пункте 1, но я не помню хранится ли текущий указатель в переменной типа File. Судя по тому, что скорость падает в 2 раза, то храниться
Altair
1.07.2004 17:30
Кстати, а мне кажется есть хороший способ ускорить процедуру EOF . Поробую ...
=== добавил позже, подумав === Нельзя никак укорить эту функцию. Где-то прога хранит текущий указатель. Вот если найти где и как она хранит его ...
BlackShadow
1.07.2004 17:35
Почитай доку по переменной типа File. Точно в одном из его полей храниться.
Altair
1.07.2004 17:39
У переменной типа FILE есть поля????? Или я того ...
BlackShadow
1.07.2004 17:44
Ты не того. Что такое File? эЭто что, что-то типа Integer или Double? Нифига. Это структура, которая хранит в себе кучу инфы (не спроста она столько памяти кушает). В "Азах" я рассказывал про Dos.TextRec. Наверняка что-то есть и для "просто File", если не то же самое.
Romtek
1.07.2004 18:23
{ Typed-file and untyped-file record }
FileRec = record Handle: Word; Mode: Word; RecSize: Word; Private: array[1..26] of Byte; UserData: array[1..16] of Byte; Name: array[0..79] of Char; end;