Главная » Free Pascal » Работа с текстовыми файлами Free Pascal

0

Обмен с текстовыми файлами очень похож на обмен с консолью (клавиатура +

+ дисплей) и выполняется с помощью тех же процедур read, readln, write, writeln. Единственная особенность заключается в том, что список ввода/вывода начинается с имени файловой переменной, ассоциированной с именем текстового файла:

var

fin: text; fout: text;

begin

assign(fin,’1.txt’);

assign(fout,’2.txt’); reset(fin); rewrite(fout);

read(fin,v1,v2,…);

writeln(fout,e1,e2,…);

Список ввода может включать имена символьных, строковых и числовых пе- ременных. Однако некоторые различия между вводом с консоли и чтением из фай- ла все-таки существуют. Во-первых, они проявляют себя при чтении строк тексто- вого файла в переменные типа char. Предположим, что мы включили в текстовый файл с именем 1.txt две следующие строки:

123456789

abcdefghi

Такими мы их видим в поле текстового редактора. Но невидимые управляющие символы в текстовом файле тоже присутствуют. И мы постараемся их "проявить" с помощью программы из листинга 10.1.

   Листинг 1 0 .1 .  Программа  txt_in1                                             

program txt_in1; var

fin: text;

ch: array [1..22] of char; i: integer;

begin

assign(fin,’1.txt’); reset(fin);

for i:=1 to 22 do begin

read(fin,ch[i]);

write(ord(ch[i]):4); end;

readln; end.

Результат ее работы, приведенный далее, придется расшифровать.

Running "c:\fpc\myprog\txt_in1.exe "

49 50 51 52 53 54 55 56 57 13 10 97 98 99 100 101 102

103 104 105 26 26

Почему мы попытались в цикле прочитать не 18 символов, которые были вид- ны на поле редактора? Мы же помним, что каждая строка в текстовом файле за- вершается признаком конца — парой кодов 0D и 0A. Поэтому девять видимых и два невидимых, по нашему предположению, должны присутствовать в обеих стро- ках. Вот мы и читаем в цикле 22 символа. Так как некоторые из считанных симво- лов относятся к группе управляющих кодов, для которых видимое изображение может отсутствовать, мы решили выдать не сами символы, а их ASCII-коды. Пер- вые 9 кодов в строке результатов соответствуют цифрам от 1 до 9. Следующий код 13 — управляющий символ CR (его шестнадцатеричный эквивалент 0D). Управ- ляющий код 10 соответствует символу LF (его шестнадцатеричный эквивалент 0A). Далее располагаются ASCII-коды букв от a до i. А вот завершающей пары CR и LF, которую мы ожидали, нет. Вместо этого в результате присутствуют два управ- ляющих кода, которые символизируют признак конца файла (EOF). На самом деле путем просмотра содержимого файла в шестнадцатеричном формате мы убеждаем- ся в том, что в первой строке признак EOL присутствует, а после данных второй строки в файле ничего нет. Откуда появились байты с кодом 26? Оказывается, что операционная система (точнее, ее подсистема управления файлами) знает фактиче- скую длину файла и после исчерпания данных генерирует байт с кодом 26. Именно на это значение среагировала бы функция EOF(fin). Этот пример лишний раз на- поминает, что при чтении данных из файла мы должны быть уверены, что в файле еще что-то есть.

В переменные строкового типа данные из текстового файла рекомендуется счи- тывать с помощью оператора readln и использовать в списке ввода единственную переменную. Байт длины в считываемой строке формируется автоматически (в файле его нет), а управляющие коды CR и LF в состав считываемых данных не включа- ются. Если длина считываемых данных превышает максимальную длину строковой переменной, то лишние хвостовые байты отбрасываются.

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

Если оператор readln сформировал значения всех переменных своего списка, а в строке, считанной из файла, данные еще есть, то следующий оператор readln бу- дет читать свои данные из новой строки.

В операторах вывода в текстовый файл write и writeln допускается использо- вание форматных указателей, определяющих длину отводимого поля и количество цифр в дробной части числа:

write(vf,e1[:w1[:d1]],e2…)

Если указание о ширине w опущено, то по умолчанию устанавливается w=23. Если задаваемая ширина слишком мала (w<10), то принудительно устанавливается w=10. Если заданное количество значащих цифр равно нулю, то ни дробная часть, ни точка (разделитель целой и дробной части) не выводятся. При d>18 принуди- тельно устанавливается d=18.

Оператор writeln отличается от оператора write тем, что завершает запись строки в файл и формирует признак конца строки.

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

Таблица 10.2

Формат обращения

Выполняемое действие

b:=EOln(vf);

Выдает True, если при чтении обнаружен признак конца строки

b:=seekeoln(vf);

Пропускает все пробелы и символы Tab до первого значащего символа или до EOL. Возвращает True при обнаружении EOL

b:=seekeof(vf);

Пропускает все пробелы, символы Tab и EOL до тех пор, пока не встретит первый значащий символ или EOF. Возвращает True при достижении EOF

Довольно часто можно услышать совет: "Чтобы избежать ошибок при работе с файлами, данные из файла надо считывать таким же образом, как они и записыва- лись". К сожалению, при работе с текстовыми файлами этот совет не всегда приводит к правильным результатам. Об этом свидетельствует программа из листинга 10.2.

   Листинг 1 0 .2 .  Программа  txt_inout                                           

program txt_inout; var

j,k1,k2: integer; f: text;

a: string=’Строка'; b: string;

begin

assign(f,’3.txt’); rewrite(f);

for j:=1 to 10 do begin

writeln(a,j:4,j*2:4);

writeln(f,a,j:4,j*2:4); end;

close(f); writeln; reset(f);

for j:=1 to 10 do begin

readln(f,b,k1,k2);

writeln(b,k1:4,k2:4); end;

close(f); readln;

end.

После запуска программы txt_inout в файл 3.txt записываются 10 строк:

Строка

1

2

Строка

2

4

Строка

10

20

В этом можно убедиться, просматривая содержимое файла после работы про- граммы. Но до конца программа не дорабатывает, т. к. на 21 строке при первом же считывании из файла фиксируется ошибка с выдачей сообщения:

Error 106 : Invalid numeric format

Все дело в том, что первой переменной в списке ввода является переменная b типа String, и ее максимальная длина равна 255 байтам. Поэтому из файла в пере- менную b считывается первая строка полностью, а при чтении числового значения в переменную k1 обнаруживается недопустимый символ, расположенный в начале второй строки. Ситуацию можно исправить, ограничив максимальную длину пере- менной b:

b:String[6];

После такого исправления результат работы программы выглядит так, как и положено:

Running "c:\fpc\myprog\txt_inout.exe " Строка  1  2

Строка 2 4

Строка 3 6

Строка 4 8

Строка 5 10

Строка 6 12

Строка 7 14

Строка 8 16

Строка 9 18

Строка 10       20

Строка  

1

2

Строка 2 4

Строка 3 6

Строка 4 8

Строка 5 10

Строка 6 12

Строка 7 14

Строка 8 16

Строка 9 18

Строка 10       20

В программе indent.pas вы можете познакомиться с новыми приемами про- граммирования (листинг 10.3). Во-первых, здесь представлена процедура, которая в качестве своих аргументов получает адреса переменных файлового типа (другим способом файловые переменные передавать нельзя). Во-вторых, запуск программы сопровождается заданием ее аргументов в командной строке. Наконец, здесь про- демонстрирована возможность не совсем обычного включения цепочки пробелов в состав выводимой строки. Цель программы заключается в сдвиге содержимого всех строк текстового файла вправо на заданное число пробелов. Операции такого рода по сдвигу выделенных блоков вправо (indent) или влево (unindent) характерны для многих текстовых редакторов.

   Листинг 10.3. Программа  indent                                              

program indent; var

f1,f2: text; name1,name2: string; k,n: integer;

procedure ind_copy(var f1,f2:text;n:integer); var

str:string;

begin

while not eof(f1) do begin

readln(f1,str); writeln(f2,‘ ‘:n,str);

end;

end; begin

if ParamCount < 3 then begin

writeln(‘Ошибка при запуске. Должно быть:’); writeln(‘indent файл1 файл2 сдвиг’);

exit; end;

name1:=ParamStr(1); name2:=ParamStr(2); Val(ParamStr(3),n,k); assign(f1,name1);   reset(f1); assign(f2,name2);   rewrite(f2); ind_copy(f1,f2,n);

close(f1);   close(f2);

end.

После запуска программы из командной строки:

>txt_inout 3.txt 4.txt 5

и просмотра содержимого файлов 3.txt и 4.txt мы наблюдаем картину, представ- ленную на рис. 10.1.

Рис. 10.1. Сдвиг содержимого в текстовом файле

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

бы одним пробелом. Количество параметров можно извлечь из системной пере- менной ParamCount. Значения параметров представлены в символьном виде масси- вом строк, откуда их можно извлекать с помощью функции ParamStr. Так как в нашем случае последний параметр представляет число (количество пробелов, вставляемое в начале каждой строки), то его приходится преобразовывать в число- вой машинный формат с помощью процедуры Val. Обратите внимание на конст- рукцию вида ‘ ‘:n, использованную при записи в файл. Она задает записываемое значение, состоящее из единственного пробела, но помимо этого содержит указа- ние, что под выводимое значение отводится поле из n позиций. Выводимый пробел прижимается к правой границе этого поля, а все лидирующие позиции также за- полняются пробелами.

Источник: Кетков, Ю. Л., Свободное программное обеспечение. FREE PASCAL для студентов и школьников, Ю. Л. Кетков, А. Ю. Кетков. — СПб.: БХВ-Петербург, 2011. — 384 с.: ил. + CD-ROM — (ИиИКТ)

По теме:

  • Комментарии