Чтение и запись данных
Мы уже знаем, что базовые операции ввода-вывода (Input-Output, I/O) в первую очередь нацелены на решение задач чтения из файла и записи в файл требуемых данных. При реализации этих операций любой язык программирования требует от нас особой внимательности и осторожности. Во-первых, следует учитывать, что перечень применяемых методов ввода-вывода определяется типом файла, с которым планируется работа. Во-вторых, необходимо соблюдать строго определенную последовательность вызова методов. В-третьих, в своем коде программист должен предусмотреть и тщательно реализовать систему обработки потенциальных ошибок.
Предлагаю вашему вниманию стандартный каркас исходного кода по работе с файлом, на который рекомендуется опираться вне зависимости от типа файла.
var F : file;
Begin
AssignFile(F,'C:\MyFile.dat'); // Связывание файловой переменной F с файлом
try
//Секция для потенциально опасных операций над файлом
finally
CloseFile(F); // Закрытие файла и освобождение переменной
end;
End.
Прокомментирую эти строки. Нами объявлена файловая переменная с именем F. Первая процедура в листинге предназначена для связывания файловой переменной F с именем файла FileName. Эту процедуру дальше будем называть процедурой инициализации базовых операций ввода-вывода.
procedure AssignFile(var F; FileName: string);
Теперь файловая переменная в состоянии держать связь с этим файлом до тех пор, пока не будет освобождена. Для разрыва связи и освобождения занятых ресурсов необходим вызов процедуры закрытия файла:
procedureCloseFile(var F);
Указанный метод завершает операции ввода-вывода. Обе процедуры всегдаприменяются в паре, и если в программе был осуществлен вызов AssignFile(), то в заключение позаботьтесь и об обязательном вызове CloseFile(). Однако при работе с файлом всегда высока вероятность появления целого спектра самых разнообразных ошибок, которые могут привести к возникновению исключительной ситуации. Именно поэтому в примере процедура закрытия вынесена в секцию finally обработчика ошибки try..finally. Такой подход гарантирует освобождение файловой переменной даже при возникновении ошибок. Более подробно особенности конструкции try..finally рассматриваются в главе 15.
Ни в коем случае не пытайтесь вызвать метод AssignFile() для файловой переменной, уже ссылающейся на другой открытый файл. При программировании всегда руководствуйтесь правилом: каждому файлу – индивидуальная файловая переменная.
Текстовые файлы
После того как мы связали файловую переменную с именем файла, в зависимости от поставленных задач можно пойти по одному из трех путей (см. алгоритм на рис. 4.1):
1. Создание нового тестового файла.
2. Открытие существующего файла в режиме только для чтения.
3. Открытие существующего файла с возможностью добавления новых строк.
Для реализации этих задач в языке Pascal предусмотрено три процедуры: Rewrite(), Reset() и Append(). Для создания нового файла вызовите метод:
procedure Rewrite(var F: File [; RecSize: Word ] );
Ключевой параметр процедуры – файловая переменная F. В результате выполнения метода формируется пустой файл с именем, определенным в процедуре инициализации AssignFile(). Если вдруг имя вновь создаваемого файла совпадет с именем существующего, то старый файл стирается без всякого предупреждения и сожаления. Второй необязательный параметр определяет, какими порциями будут осуществляться операции записи данных в файл. По умолчанию назначается размер, равный 128 байт. При работе с текстовыми файлами этот параметр не используется, но играет важную роль для двоичных файлов.
Для открытия уже существующего файла процедура Rewrite() не нужна. Вместо нее воспользуйтесь методом инициализации чтения:
procedureReset(var F [: File; RecSize: Word ] );
Параметры процедуры идентичны аргументам предыдущего метода. После открытия внутренний указатель файла позиционируется на самом первом его байте. При использовании метода Reset() надо иметь в виду, что режим открытия файла этой процедурой зависит от значения глобальной переменной FileMode. По умолчанию в ней содержится значение 2, что соответствует режиму, допускающему как чтение, так и запись. Если планируется работа с файлом только в режиме чтения, то перед вызовом Reset() присвойте переменной FileMode значение 0. Соответственно, если файл открывается только для записи, установите переменную в значение 1.
И наконец, текстовый файл может открываться в режиме добавления данных в конец файла. Для этого вызывается процедура:
procedure Append(var F: Text);
После выполнения процедуры внутренний указатель файла позиционируется на самом последнем байте файла.
Осталось привести несколько простых поясняющих примеров. Первый из них создает новый файл в корне диска C:\ и заполняет его десятью символами A.
programDemoTxt1;
{$APPTYPE CONSOLE}
uses SysUtils;
varF : TextFile;
i : integer;
Begin
AssignFile(F,'C:\NewFile.txt');
Try
Rewrite(F);
for i:=0 to 9 do Write(F,'A');
Finally
CloseFile(F);
end;
End.
Второй пример – скромная консольная программка, осуществляющая вывод содержимого текстового файла autoexec.bat с последующим отображением прочитанной информации на экран компьютера.
program DemoTxt2;
{$APPTYPE CONSOLE}
uses SysUtils;
var F : TextFile;
s : string;
Begin
AssignFile(F,'C:\Autoexec.bat');
Reset(F);
TRY
while SeekEof(f)=False do //проверка местоположения указателя
begin //пока указатель не достиг последней строки файла
ReadLn(F,S); //считываем очередную строку в переменную S
WriteLn(s); //и отображаем считанную информацию на экране
end;
FINALLY
CloseFile(F);
END;
ReadLn;
End.
Третий пример добавляет десять строк в конец текстового файла. Он также не должен вызвать особых затруднений, только не забудьте перед запуском программы создать в корне диска <C:> файл MyFile.txt, иначе программа выразит свое недоумение по поводу отсутствия открываемого файла.
program DemoTxt3;
{$APPTYPE CONSOLE}
uses SysUtils;
var F : TextFile;
i : integer;
Begin
AssignFile(F,'C:\MyFile.txt');
Append(F);
TRY
for i:=0 to 9do WriteLn(F,'Строка -', i);
Flush(f);
FINALLY
CloseFile(F);
END;
ReadLn
End.
Уверен, что в предложенных листингах внимательный читатель заметил ряд новых методов. В первую очередь это процедуры, осуществляющие чтение Read() и запись Write() данных.
Процедуры Read() и Write() весьма часто применяют в консольных приложениях для обычного взаимодействия с пользователем, т. к. последние способны работать не только с файлами, но и с клавиатурой и консолью.
program DemoCns;
{$APPTYPE CONSOLE}
usesSysUtils;
var s : string;
Begin
Write('Insert name: ');
Readln(s);
Writeln('Name: ',s);
Writeln('Press any key to exit');
Readln;
end;
End.
procedureRead( [ var F: Text; ] V1 [, V2,...,Vn ] );
procedure ReadLn([ var F: Text; ] V1 [, V2,...,Vn]);
procedure Write([ var F: Text; ] P1 [, P2,..., Pn]);
procedure WriteLn([ var F: Text; ] P1 [, P2,...,Pn]);
Все четыре процедуры вооружены идентичными параметрами. Первый аргумент, F, соответствует файловой переменной текстового файла. В качестве второго аргумента в процедурах чтения указывают переменную, в которую осуществляется чтение данных из файла, а в процедурах записи, наоборот, данные, содержащиеся в этой переменной, записываются в файл. Обратите внимание на ряд необязательных параметров в квадратных скобках [, V2,...,Vn].
При желании программист может ими воспользоваться, как в примере добавления строк в конец файла, где помимо текстовой информации 'Строка -' в файл записывается номер шага в цикле. Окончание …ln (от англ. line) в имени процедуры говорит нам о том, что процедура нацелена на работу со строками.
Очистка буфера текстового файла осуществляется методом:
procedure Flush (var F: Text);
Вызов этого метода целесообразен в том случае, когда файл был открыт для записи. Функция гарантирует, что все данные из буфера будут сохранены в файл на диске. Эта процедура вызывается по окончании операций записи данных в файл.
Познакомимся с еще одной весьма полезной функцией с именем Eof() (сокращение от англ. End of file), в чьи обязанности входит проверка того, не находится ли внутренний указатель файла на самой последней его строке.Другими словами, не достигнут ли еще конец файла.
function Eof[ (var F: Text) ]: Boolean;
Этот метод обычно применяется при организации чтения данных из файла. Вернитесь к листингу проекта, демонстрирующего способ чтения файлаautoexec.bat. Здесь метод Eof() вызывается внутри цикла while…do. Пока функция возвращает значение false (признак того, что конец файла еще не достигнут), продолжается выполнение операций чтения. Каждый вызов метода WriteLn() заставляет указатель файла перемещаться на одну строку вперед, все ближе и ближе к концу файла.
Специально для текстовых файлов реализован «продвинутый» метод проверки достижения конца файла:
function SeekEof[ (var F: Text) ]: Boolean;
Отличие метода SeekEof() от обычного Eof() в том, что он умеет распознавать пустые строки (заполненные символами пробела) и исключать их из процесса чтения.
Раз мы заговорили о проверках на нахождение указателя в конце файла, то стоит упомянуть тест на нахождение указателя в конце строки текстового файла.
function EoLn[ (var F: Text) ]: Boolean;
Соответственно аналогичный метод, но игнорирующий пробелы:
function SeekEoLn[ (var F: Text) ]: Boolean;
Для лучшего понимания поведения методов SeekEof() и SeekEoLn() изучите предлагаемый код. В примере предложен способ хранения целых чисел в текстовом файле.
programDemoSeek;
{$APPTYPE CONSOLE}
uses SysUtils;
var f: TextFile;
i: Integer;
Begin
AssignFile(f,'c:\space.txt');
TRY
//создание демонстрационного файла
Rewrite(f);
Writeln(f, ' 1 2 3 4 5 '); // целые числа, разделенные пробелами
Writeln(f, ' '); // вносим пустые строки для демонстрации
// работы метода SeekEof
Writeln(f, ' ');
Writeln(f, ' 55 123 6 35 0 77');
//в файл записаны 4 строки
Reset(f); //переходим к операциям чтения
while SeekEof(f)=false do // цикл построчного чтения, игнорирующий
// пустые строки
Begin
while SeekEoln(f)=false do // цикл чтения чисел из строки,
// игнорирующий пробелы
Begin
Read(f, i);
Writeln(i);
end;
end;
FINALLY
CloseFile(f);
END;
Readln;
End.
Повторившие этот пример увидят, что, несмотря на наличие пустых строки пробелов между символами, программа выявила целые числа и вывела их на экран в один столбец.
Дата добавления: 2016-03-15; просмотров: 1506;