Помощь - Поиск - Пользователи - Календарь
Полная версия: Файлы
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи > FAQ
volvo
Работа с файлами


Тип-файл представляет собой последовательность компонент одного типа, расположенных на внешнем устройстве (например, на диске).

Любой файл имеет 3 характерные особенности:
  • у него есть имя (что позволяет программе работать одновременно с несколькими файлами);
  • он содержит компоненты одного типа (компоненты могут быть любого типа, за исключением самого типа-файла, то есть нельзя создать "файл файлов")
  • длина вновь создаваемого файла никак не оговаривается при его объявлении и ограничивается только емкостью внешней памяти и возможностями операционной системы.
Работа с физическими файлами происходит через так называемые файловые переменные. Файловая переменная в Паскале - это любая переменная файлового типа. В Паскале имеются три класса файлов: типизированный файл, текстовый файл, нетипизированный файл.

Для задания типа-файла следует использовать зарезервированные слова File и Of, после чего указать тип компонент файла.

Пример:
Type
N = File Of Integer; {Тип-файл целых чисел}
C = File Of Char; {Тип-файл символов}


Есть заранее определенный в Паскале тип файла с именем Text. Файлы этого типа называют текстовыми.

Введя файловый тип, можно определить и переменные файлового типа:
Var
F1 : N;
F2 : C;
F3 : Text;


Тип-файл можно описать и непосредственно при введении файловых переменных:
Var
Z : File Of Word;


Файловые переменные имеют специфическое применение. Над ними нельзя выполнять никаких операций (присваивать значение, сравнивать и т.д.). Их можно использовать лишь для выполнения операций с файлами (чтение, запись и т.д.).

Элементы файла считаются расположенными последовательно, то есть так же, как элементы линейного массива. Отличие же состоит в том, что, во-первых, размеры файла могут меняться, во-вторых, способ обращения к элементам совсем другой: невозможно обратиться к произвольному элементу файла; элементы его просматриваются только подряд от начала к концу, при этом в каждый момент времени доступен только один элемент. Можно представить себе, что для каждого файла существует указатель, показывающий в данный момент на определенный компонент файла. После проведения операции чтения или записи указатель автоматически передвигается на следующий компонент.

Assign(<Имя файловой переменной>,<Имя файла>);
Перед использованием файловой переменной она должна быть связана с конкретным внешним файлом с помощью вызова процедуры Assign. Внешним файлом обычно является поименованный файл на диске, но он также может представлять собой устройство, как например, клавиатуру или дисплей. Во внешних файлах сохраняется записанная в файл информация, или они служат источниками информации, которая считывается из файла.

Имя файла задается либо строковой константой, либо через переменную типа String. Имя файла должно соответствовать правилам работающей в данный момент операционной системы. Если строка имени пустая, то связь файловой переменной осуществляется со стандартным устройством ввода-вывода (как правило - с консолью).

Когда связь с внешним файлом установлена, для подготовки ее к операции ввода или вывода файловая переменная должна быть "открыта". Существующий файл можно открыть с помощью процедуры Reset (указатель текущей компоненты файла настраивается на начало файла; если физического файла, соответствующего файловой переменной не существует, то возникает ситуация ошибки ввода-вывода):
Reset(<Имя файловой переменной>);

а новый файл можно создать и открыть с помощью процедуры Rewrite (открывается новый пустой файл для записи, ему присваивается имя, заданное процедурой Assign. Если файл с таким именем уже существует, то он уничтожается):
Rewrite(<Имя файловой переменной>);

Для текстовых файлов может быть использована еще одна процедура открытия файла (указатель файла устанавливается в его конец)
Append(<Имя файловой переменной>);

Текстовые файлы, открытые с помощью процедуры Reset, доступны только для чтения, а текстовые файлы, открытые с помощью процедуры Rewrite и Append, доступны только для записи. Типизированные и нетипизированные файлы всегда допускают как чтение, так и запись, независимо от того, были они открыты с помощью процедуры Reset или с помощью процедуры Rewrite.

Когда программа завершит обработку файла, он должен закрываться с помощью стандартной процедуры Close. После полного закрытия файла, связанный с ним внешний файл обновляется. Затем файловая переменная может быть связана с другим внешним файлом.
Close(<Имя файловой переменной>);
Внимание: Это требование обязательно должно соблюдаться для файла, в который производилась запись !


Последовательный и прямой доступ
Обычно доступ к файлам организуется последовательно, то есть, когда элемент считывается с помощью стандартной процедуры Read или записывается с помощью стандартной процедуры Write, текущая позиция файла перемещается к следующему по порядку элементу файла. Однако к типизированным и нетипизированным файлам можно организовать прямой доступ с помощью стандартной процедуры Seek (которая перемещает текущую позицию файла к заданному элементу):
Seek(<Имя файловой переменной>, <Номер компоненты>);

Текущую позицию в файле и текущий размер файла можно определить с помощью стандартных функций FilePos (возвращает значение типа LongInt, содержащее порядковый номер компоненты, которая будет обрабатываться следующей операцией ввода-вывода) и FileSize (возвращает значение типа LongInt, которое содержит количество компонентов файла):
FilePos(<Имя файловой переменной>);
FileSize(<Имя файловой переменной>);
Внимание: Функции прямого доступа неприменимы к текстовым файлам !

Чтение и запись
Теперь рассмотрим непосредственную организацию чтения и записи.

Любой файл представляет собой линейную последовательность элементов, каждый из которых имеет сложный тип (или тип записи) файла. Каждый элемент файла имеет номер. Первый элемент файла считается нулевым элементом.

Для ввода информации из файла, открытого для чтения, используется оператор Read. Правда, в его формате и использовании есть некоторые изменения:
Read(<Имя файловой переменной>, <Список ввода>);

Происходит считывание данных из файла в переменные, имена которых указаны в списке ввода. Переменные должны быть того же типа, что и компоненты файла.

Вывод информации производит, как можно догадаться, оператор:
Write(<Имя файловой переменной>, <Список вывода>);

Данные из списка вывода заносятся в файл, открытый для записи.
Любопытно, что вывод данных на монитор и ввод с клавиатуры в языке Паскаль тоже являются действиями с файлами. Они даже имеют свои предопределенные файловые переменные текстового типа: Output и Input соответственно. Переменная Output всегда открыта для записи, Input - для чтения. Если не указывать файловые переменные в операторах ввода-вывода, то в случае записи по умолчанию выбирается файл Output, в случае чтения - Input.

Любой файл конечен и продолжать чтение из него информации можно лишь до определенного предела. Как этот предел установить? Проверить, окончен ли файл, можно вызовом стандартной логической функции:
Eof(<Имя файловой переменной>)
Она возвращает значение True, если файл окончен, и False - в противном случае.
volvo
Текстовые файлы
В этом разделе описываются операции ввода/вывода, использующие файловую переменную стандартного типа Text. В Turbo Pascal тип Text отличается от типа file of char. При открытии текстового файла внешний файл интерпретируется особым образом: считается, что он представляет собой последовательность символов, сгруппированных в строки, где каждая строка заканчивается символом конца строки (end of line), который представляет собой символ перевода каретки (Chr(13)), за которым, возможно, следует символ перевода строки (Chr(10)).

Для текстовых файлов существует специальный вид операций чтения и записи (Read<Ln> и Write<Ln>), которые позволяют считывать и записывать значения, тип которых отличается от типа Char. Такие значения автоматически переводятся в символьное представление и обратно. Например, Read(F, i), где i - переменная целого типа, приведет к считыванию последовательности цифр, интерпретации этой последовательности, как десятичного числа, и сохранению его в i.

Как было отмечено ранее, имеются две стандартные переменные текстового типа - Input и Output. Стандартная файловая переменная Input - это доступный только для чтения файл, связанный со стандартным файлом ввода операционной системы (обычно это клавиатура), а стандартная файловая переменная Output - это доступный только для записи файл, связанный со стандартным файлом вывода операционной системы (обычно это дисплей).
Перед началом выполнения программы файлы Input и Output автоматически открываются, как если бы были выполнены следующие операторы:
Assign(Input,''); Reset(Input);
Assign(Output,''); Rewrite(Output);

Аналогично, после выполнения программы эти файлы автоматически закрываются.

Если программа использует стандартный модуль Crt, то файлы Input и Output не будут по умолчанию относиться к стандартным файлам ввода/вывода. Для некоторых стандартных процедур, список которых приведен в данном разделе, не требуется явно указывать в качестве параметра файловую переменную. Если этот параметр опущен, то по умолчанию будут рассматриваться Input и Output, в зависимости от того, будет ли процедура или функция ориентирована на ввод или вывод. Например, Read(Х) соответствует Read(Input,Х) и Write(Х) соответствует Write(Output,Х).

Если при вызове одной из процедур или функций из этого раздела задается файл, этот файл должен быть связан с внешним файлом с помощью процедуры Assign и открыт с помощью процедуры Reset, Rewrite, или Append. Если для ориентированной на вывод процедуры или функции указывается файл, который был открыт с помощью процедуры Reset, то выведется сообщение об ошибке.

Аналогично, будет ошибкой задавать для ориентированной на ввод процедуры или функции файл, открытый с помощью процедур Rewrite или Append.


Процедуры/функции для работы с текстовыми файлами

Процедуры:

Append
Открывает существующий файл для добавления
Flush
Выталкивает буфер файла вывода
Read
Считывает одно или более значений из текстового файла в одну или более переменных
Readln
Выполняет те же действия, что и Read, а потом делает пропуск до начала следующей строки файла
SetTextBuf
Назначает буфер ввода/вывода для текстового файла
Write
Записывает в текстовый файл одно или более значений
Writeln
Выполняет те же действия, что и Write, а затем добавляет к файлу маркер конца строки

Функции:

Eoln
Возвращает для файла состояние end-of-line (конец строки)
SeekEof
Возвращает для файла состояние end-of-file (конец файла)
SeekEoln
Возвращает для файла состояние end-of-line (конец строки)


Нетипизированные файлы
Нетипизированные файлы представляют собой каналы ввода/вывода нижнего уровня, используемые в основном для прямого доступа к любому файлу на диске, независимо от его типа и структуры. Любой нетипизированный файл объявляется со словом file без атрибутов, например:
var
Datafile : file;


Для нетипизированных файлов в процедурах Reset и Rewrite допускается указывать дополнительный параметр, чтобы задать размер записи, использующийся при передаче данных. По умолчанию длина записи равна 128 байт. Предпочтительной длиной записи является длина записи, равная 1, поскольку это единственное значение, которое точно отражает размер любого файла (если длина записи равна 1, то неполные записи невозможны).

За исключением процедур Read и Write для всех нетипизированных файлов допускается использование любой стандартной процедуры, которую разрешено использовать с типизированными файлами. Вместо процедур Read и Write здесь используются соответственно процедуры BlockRead и BlockWrite, позволяющие пересылать данные с высокой скоростью.

Процедуры для работы с нетипизированными файлами

BlockRead
Считывает в переменную одну или более записей
BlockWrite
Записывает одну или более записей из переменной


Обработка ошибок ввода-вывода

По умолчанию, при всех обращениях к стандартным функциям и процедурам ввода/вывода автоматически производится проверка на наличие ошибок. При обнаружении ошибки программа прекращает работу и выводит на экран сообщение об ошибке. С помощью директив компилятора {$I+} и {$I-} эту автоматическую проверку можно включить или выключить.
Когда автоматическая проверка отключена, то есть когда процедура или функция была скомпилирована с директивой {$I-}, ошибки ввода/вывода, возникающие при работе программы, не приводят к ее останову. При этом, чтобы проверить результат выполнения операции ввода/вывода, нужно использовать стандартную функцию IOResult.
...
Assign(f, 'a.txt');
{$I-} Reset(f); {$I+}
If IOResult <> 0 Then
Writeln('Файл не может быть открыт...')
Else
Begin
{ Работа с файлом }
...
Close(f)
End;
...


Переменная FileMode
Переменная FileMode, определенная в модуле System, устанавливает код доступа, который передается в DOS, когда типизированные и нетипизированные файлы (но не текстовые) открываются с помощью процедуры Reset.

По умолчанию задается значение FileMode равное 2, которое разрешает и чтение, и запись. Присваивание другого значения переменной FileMode приводит к тому, что все последующие вызовы процедуры Reset будут использовать этот режим.

Диапазон возможных значений FileMode зависит от используемой версии DOS. Однако для всех версий задаются следующие режимы:

0 : только чтение
1 : только запись
2 : чтение/запись

Примечание: Новые файлы, созданные с помощью процедуры Rewrite, всегда открываются в режиме Read/Write, соответствующем значению переменной FileMode = 2.

Таблица процедур/функций ввода - вывода

Общие процедуры/функции ввода - вывода

Процедуры:

Assign
Присваивает имя внешнего файла файловой переменной
ChDir
Меняет текущий справочник
Close
Закрывает открытый файл
Erase
Удаляет внешний файл
GetDir
Возвращает текущий справочник на заданном диске
MkDir
Создает подсправочник
Rename
Переименовывает внешний файл
Reset
Открывает существующий файл
Rewrite
Создает и открывает новый файл
RmDir
Удаляет пустой подсправочник
Seek
Передвигает текущую позицию файла на указанную компоненту (НЕ используется с текстовыми файлами !!)
Truncate
Усекает размер файла до текущей позиции в файле (НЕ используется с текстовыми файлами !!)

Функции:

Eof
Возвращает для файла состояние end-of-file (конец файла)
FilePos
Возвращает текущую позицию в файле (НЕ используется с текстовыми файлами !!)
FileSize
Возвращает текущий размер файла (НЕ используется с текстовыми файлами !!)
IOResult
Возвращает целое значение, являющееся состоянием последней выполненной операции ввода/вывода


Пример обработки файлов
Для примера решим следующую задачу: "Написать программу, которая вводит с клавиатуры список фамилий учащихся, а затем распечатывает его, кроме тех учащихся, у которых фамилия начинается с буквы 'А'".

Так как заранее количество данных не известно, то для их хранения используем файл. Тип элементов - строковый.
Var
I,N : Integer;
F : File Of String;
S : String;

Begin
Assign(F,'Spis.lst'); {Связываем переменную F с файлом Spis.lst}
Writeln('Введите количество учащихся');
Readln(N); {Вводим количество учащихся}
Rewrite(F); {Создаем файл для записи в него данных}
For I:=1 To N Do {Для всех учащихся}
Begin
Writeln('Введите фамилию');
Readln(S);
Write(F,S)
End;
Close(F);
Reset(F);
Writeln; Writeln('Список учащихся:');
While Not(Eof(F)) Do
Begin
Read(F,S);
If S[1]<>'А' Then Writeln(S)
End;
Close(F)
End.
Altair
Копирование файлов.

1 способ.
Читать его в буфер через BlockRead, а затем записывать через
BlockWrite.
Код

procedure FileCopy(fileFrom, fileTo: string);
var
f1,f2:file;
p:pointer;
rb:word;
Begin
Assign(f1,fileFrom); FileMode:=0; Reset(f1,1);
Assign(f2,fileTo); ReWrite(f1,1);
GetMem(p,32768);
If p=nil then begin WriteLn('Not enough memory !'); Halt; end;
Repeat
BlockRead(f1,p^,32768,rb);
BlockWrite(f2,p^,rb);
Until rb<>32768;
FreeMem(p,32768);
Close(f2); Close(f1);
End;

2 способ.
Более изящный вариант, реализованный в следующей программе:
Код
Uses Objects;
Var
S1, S2: TBufStream;
Begin
If ParamCount <> 2 Then Halt(1);
S1.Init(ParamStr(1), stOpenRead);
S2.Init(ParamStr(2), stCreate);
S2.CopyFrom(S1, S1.GetSize);
S2.Done;
S1.Done;
End.

3 способ.
использовать команду MS-DOS COPY, но в таком случае необходимо использовать вызов командного процессора:
Код

{...}
Swapvectors;
Exec(<путь к command.com>,'/C COPY FILE1 toFILE2');
Swapvectors;

Путь к ком. процессору можно получить используя переменную окружения COMSPEC, а в команде соответственно задаются имена файлов для копирования...

4 способ.
Программа копирования файлов (одного файла за раз) с использованием буфера в XMS:
Нажмите для просмотра прикрепленного файлаДополнительный файл
Нажмите для просмотра прикрепленного файла

Поиск файла по директориям
Hеобходимо воспользоваться процедурами FindFirst/FindNext и
рекурсией.
Код
{Вот пример самой простенькой программки. Алгоритм тут весьма
прозрачен, так что без комментариев.}
uses Dos;
{
Эта программа ищет все файлы по маске turbo.* в поддиректориях
папки C:\ и выводит на экран их полные имена =)
Основа программы - функция SearchDir её параметры -
fn - маска, Dir -начальная директория.
}
procedure SearchDir(fn, Dir:string);
var
SRec: SearchRec;
ckl:integer;
F:file;
regs:registers;
begin
if dir[length(dir)]<>'\' then Dir:=Dir+'\';

FindFirst(Dir+fn, AnyFile, SRec);
while DosError = 0 do begin
WriteLN(Dir+SRec.Name);
FindNext(SRec);
End;
FindFirst(Dir+'*.*', Directory, SRec);
while DosError = 0 do begin
with SRec do
if (Attr and 16 <> 0 ) and (Name[1]<>'.') then
SearchDir(fn,Dir+Name);
FindNext(SRec);
end;
end;

Begin {program}
SearchDir('turbo.*', 'C:\');
End. {program}


Удаление или откыртие на запись файла с атрибутом read/only.

Нужно снять атрибут r/o с файла, а затем делать с ним все, что
заблагорассудится.
Код
Uses DOS;
var
t:text;
attr:Word;
Begin
Assign(t,'file');
GetFAttr(t,attr);
attr:=attr and $FE;
SetFAttr(t,attr);
Append(t);
Writeln(t,'Hello!');
Close(t);
attr:=attr or $01;
SetFAttr(t,attr);
End.


Удаление строки из текстового файлаО: Надо переписать файл
Код
procedure DelStrInFile(filename,S:string);
{filename -имя файла, s - удаляемая строка }
var
f,f1:text;
ts: string;
begin
Assign(f,filename);
reset(f);
Assign(f1,'tempfile.dat');
rewrite(f1);
While no eof(f) do
begin
readln(f,ts);
If ts<>s then writeln(f1,s)
end;
close(f1); close(f);
erase(f); rename(f1,filename)
end;


Как открыть в программе больше 14 файлов?
Используйте в вашей программе вот такой модуль. Можете до 255 файлов открыть.
Код
{$IFDEF DPMI}
STOP COMPILE ! Only for real mode !
{$ENDIF}

Unit Extend; {(C) 1996 by Pavel Nikiforov}
interface
implementation
procedure Setup;
type PJFT=^TJFT;
    TJFT=record
           Num:word;
           Tbl:PChar;
         end;

var MyJFT:PChar;
   P:PJFT;
begin
getmem(MyJFT,255);
FillChar(MyJFT[0],255,$FF);
P:=Ptr(PrefixSeg,$32);
move(P^.TBL^,MyJFT^,P^.Num);
P^.TBL:=MyJFT;
P^.Num:=255;
end;
begin
Setup;
end.

--------------------------------------


Где взять описание <такого-то> формата файлов?

http://www.wotsit.org
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.