Files doc Гречкина П. В. Текстовый файл. Исключения Стр
Вид материала | Документы |
- Название доклада, 54.33kb.
- Г. Ч. Драконов (инициалы, фамилия автора, шрифт жирный), 85.62kb.
- Правила оформления печатных материалов Материалы конференции представляются в оргкомитет, 49.34kb.
- «3» дана информация о том, что называют малыми телами, их классификация, отсутствует, 5.83kb.
- Word. Задание "Редактирование текста", 14.24kb.
- Текстовые редакторы это программы для создания и редактирования текстовых документов, 263.8kb.
- Текстовый редактор. Работа с текстом Текстовый редактор (ТР), 62.2kb.
- Закон приморского края, 196.64kb.
- Лекция 11 doc V- 0,2, 710.33kb.
- Тема Ввод-вывод и файловая система. Файл 351111. doc, 294.63kb.
Files.doc Гречкина П.В. Текстовый файл. Исключения Стр.
Файл
При использовании файлов в программе (в качестве источников входных данных или для записи выходных данных) файл представляется в двух аспектах:
- физическом; это именованная область памяти на внешнем носителе (диске), служащая для хранения данных; идентифицируется именем согласно правилам операционной системы (MS DOS, Windows и т.д.);
- логическом; это представление файла в программе, зависящее от правил языка программирования; В Паскале файл в программе представляется файловой переменной, имя которой строится по обычным правилам Паскаля.
Входной файл создается любым подходящим способом независимо от программы и до ее запуска. Выходной файл формируется программой.
Связь логического и физического представлений
Соответствие между физической и логической организацией устанавливается специальным оператором языка, связывающим физическое имя файла с файловой переменной; с этого момента программа имеет дело с файлом посредством этой файловой переменной, и термин «файл» применительно к операторам обработки файлов относится к файловой переменной (корректная формулировка звучала бы, например, так: «... чтение из файла, представленного файловой переменной f» вместо краткого: «чтение из файла f»). Этот оператор:
AssignFile(<ф.п.>,’<имя файла>’);
Типы файлов
В языке Паскаль существует три вида файлов: текстовые, типизированные, нетипизированные (бестиповые, двоичные). Чаще всего будем использовать текстовый файл.
Структура файла
Для сравнения рассмотрим структуру типизированного и текстового файлов. Изобразим файл в виде полосы последовательно расположенных байтов. Любой файл заканчивается символом конца файла eof (первые буквы слов фразы «end of file»).
Типизированный файл (следующий семестр)
В
![](images/374631-nomer-634e71d9.gif)
![](images/374631-nomer-481c3930.gif)
![](images/374631-nomer-481c3930.gif)
![](images/374631-nomer-m3163f05c.gif)
![](images/374631-nomer-318e66c1.gif)
![](images/374631-nomer-2b23fba0.gif)
![](images/374631-nomer-md8025d0.gif)
![](images/374631-nomer-m2a7690f7.gif)
![](images/374631-nomer-m333e9a93.gif)
![](images/374631-nomer-481c3930.gif)
![](images/374631-nomer-m333e9a93.gif)
Компоненты размещены непосредственно один за другим.
Файл хранится только на внешнем запоминающем устройстве (в частности, на диске).
Описание файловой переменной:
![](images/374631-nomer-39a00875.gif)
<ф.п.>:file of <тип_компонентов>;
Значение файловой переменной – файл с компонентами заданного типа.
Такие файлы мы будем изучать во втором семестре.
Текстовый файл
Текстовый файл – совокупность строк (последовательностей символов) переменной длины, заканчивающихся специальным символом eoln (конец строки; на клавиатуре набирается нажатием клавиши Enter):
![](images/374631-nomer-m16fca2bb.gif)
![](images/374631-nomer-2b23fba0.gif)
![](images/374631-nomer-m3d96e5b.gif)
![](images/374631-nomer-2b23fba0.gif)
![](images/374631-nomer-656f533f.gif)
![](images/374631-nomer-2b23fba0.gif)
![](images/374631-nomer-m16fca2bb.gif)
![](images/374631-nomer-m333e9a93.gif)
![](images/374631-nomer-m3163f05c.gif)
![](images/374631-nomer-26f97d91.gif)
![](images/374631-nomer-2b23fba0.gif)
![](images/374631-nomer-2b23fba0.gif)
![](images/374631-nomer-md8025d0.gif)
![](images/374631-nomer-m2a7690f7.gif)
![](images/374631-nomer-m1c34be47.gif)
![](images/374631-nomer-m333e9a93.gif)
![](images/374631-nomer-4661bb9b.gif)
![](images/374631-nomer-6d8bb12d.gif)
![](images/374631-nomer-5cb6945d.gif)
![](images/374631-nomer-5cb6945d.gif)
![](images/374631-nomer-m2c1b32d5.gif)
Описание файловой переменной:
![](images/374631-nomer-39a00875.gif)
<ф.п.>: TextFile; или просто Text;
Набранные на клавиатуре данные представляют собой стандартный входной файл. Содержимое дисплея при просмотре любого файла – стандартный выходной файл. Эти файлы используются при задании и просмотре данных. Для хранения данных последние записываются в файл на внешнем запоминающем устройстве (диске).
В консольном приложении можно использовать стандартные файловые переменные – input (по умолчанию связан со стандартным входным текстовым файлом – клавиатурой) и output (по умолчанию связан со стандартным выходным текстовым файлом – дисплеем). Ввод/вывод можно перенаправить в другие текстовые файлы. Пример смотрите в файле TextFile.doc.
Когда файлов несколько, или вы создаете неконсольное приложение, необходимо создавать собственную файловую переменную. Далее во всех задачах этого семестра будем использовать собственные файловые переменные и осуществлять ввод и вывод через нестандартные текстовые файлы. В них кириллица выводится корректно, т.к кодировки редактора кода и просмоторщика текстовых файлов Windows совпадают (по умолчанию).
Описание собственной файловой переменной
![](images/374631-nomer-m3a57a307.gif)
Здесь:
ф.п. – файловая переменная,
TextFile - стандартный тип (можно просто Text).
Var
<ф.п.>: TextFile;
Специфика
Компоненты-строки представлены во внешнем (символьном) виде: каждый байт являет собой код символа согласно таблице кодов.
В программе из текстовых файлов вводятся и выводятся только неструктурированные данные – числа, символы, а также строки. Структурированные данные (массивы, записи) необходимо вводить по компонентам структуры (элементам, полям).
Числа разделяются пробелами, табуляциями и/или символами конца строки – eoln.
Символы считываются подряд (eoln – тоже символ!).
Строки – про правила считывания строк – подробнее во втором семестре.
Преимущества использования текстовых файлов перед остальными:
- простота создания (непосредственный набор данных на клавиатуре);
- наглядность (непосредственный просмотр средствами текстовых редакторов);
- универсальность (можно обойтись только этим видом файлов).
Недостатки
– низкая скорость обработки, часто совмещенной с распознанием.
– неравномерность размеров «порций»-строк и как следствие – только последовательный доступ
– невозможность редактирования «на месте» (либо чтение, либо (до)запись, но не одновременно)
Основные операторы для работы с текстовыми файлами:
assignFile( <ф.п.>,’<имя файла>’) – связывает файловую переменную с файлом;
rewrite( <ф.п.> ) – создание и открытие нового файла для записи;
reset (<ф.п.> ) – открытие существующего текстового файла (файла, связанного с файловой переменной <ф.п.>) для чтения;
append( <ф.п.> ) – открытие существующего текстового файла (файла, связанного с файловой переменной <ф.п.>) для дозаписи в конец;
closeFile( <ф.п.>) – закрытие открытого файла.
Операторы ввода-вывода:
read( <ф.п.>,<список ввода>) – чтение данных; элемент списка ввода для текстового файла – число или символ или строка string;
write( <ф.п.>,<список вывода>) - запись данных согласно списку вывода; элемент списка вывода для текстового файла – число или символ или строка string.
readln( <ф.п.>,<список ввода>) - чтение данных согласно списку ввода и переход на следующую строку; если в строке данных остались данные, не вошедшие в список ввода, они игнорируются
writeln( <ф.п.>,<список вывода>) - запись данных в файл согласно списку вывода с добавлением в конце выведенной строки маркера конца строки (переход на следующую строку).
Другие процедуры и функции, применимые для работы с текстовыми файлами:
Eof Возвращает TRUE, если конец файла (символ конца файла (End-Of-File)), и FALSE в противном случае. eof(<ф.п.>), например, eof(dat)
SeekEof Возвращает TRUE, если до конца файла (до символа конца файла (End-Of-File)) остались только пробелы и символы конца строки, и FALSE в противном случае. SeekEof(<ф.п.>), например, seekeof(dat)
Eoln Возвращает TRUE, если конец строки (символ eoln (End-Of-Line)) в файле, и FALSE в противном случае. eoln(<ф.п.>), например, eoln(dat)
SeekEoln Возвращает TRUE, если до конца строки (до символа eoln (End-Of-Line)) в файле остались только пробелы, и FALSE в противном случае. seekeoln(<ф.п.>), например, seekeoln(dat)
Rename Переименовывает внешний файл. Rename(<ф.п.>, <новое_имя>), например, Rename(dat, ‘new_file.txt’)
Erase Удаляет внешний файл. Erase(<ф.п.>), например, Erase(dat). Перед удалением файла убедитесь, что закрыли его.
GetDir Возвращает имя текущей директории (папки) на заданном диске. GetDir(<диск>, <строковая_переменная>), например, GetDir(0, S). диск: 0 – текущий, 1 – A, 2 – B, 3 – C и т.д.
ChDir Изменение текущей директории (папки). ChDir(<полное_имя_папки>), например, Chdir(‘D:\Tmp’)
MkDir Создает поддиректорию (дочернюю папку). MkDir(<полное_имя_папки>),например, MkDir(‘D:\Tmp\New’)
RmDir Удаляет пустую поддиректорию (дочернюю папку). RmDir(<полное_имя_папки>),например, RmDir(‘D:\Tmp\New’)
IOResult Возвращает целое значение – код ошибки последней выполненной операции ввода/вывода, если отключить автоматическую проверку ошибок ввода/вывода (используя опцию компилятора {$I-}. Если IOResult вернула 0, последняя операция выполнена без ошибок. Альтернативный способ обработки ошибок – обработка исключительных ситуаций при включенной опции {$I+}.
С проверкой ошибок (возвращают True/False) есть в модуле SysUtils функции: CreateDir(<полное_имя_папки>), DirectoryExists(<полное_имя_папки>), FileExists(<имя_файла>), RemoveDir(<полное_имя_папки>), RenameFile(<старое_имя_файла>,<новое_имя_файла>), DeleteFile(<имя_файла>).
Итак, перед использованием файловой переменной, ее надо связать с внешним файлом с помощью процедуры AssignFile. Внешний файл – это обычно дисковый файл, но им может быть и устройство, такое как клавиатура или дисплей. Внешний файл хранит информацию, записанную в файл, или позволяет читать информацию из файла.
После связывания с внешним файлом, файловая переменная должна быть «открыта» для ввода или вывода. Существующий файл может быть открыт для чтения с помощью Reset (только чтение) или Append (только запись в конец файла), а новый файл может быть создан и открыт только для записи с помощью процедуры Rewrite.
Каждый файл – это линейная последовательность компонент.
Текстовый файл является файлом последовательного доступа, т.е. прочитать/записать третью строку можно только прочитав/записав первые две строки. Например:
Readln(dat); Readln(dat); Read(dat, a); или Writeln(res); Writeln(res); Write(res, a);
После завершения работы с файлом его следует закрыть с помощью стандартной процедуры CloseFile. Файл будет обновлен, а файловую переменную можно связывать с другим внешним файлом.
По умолчанию все обращения к стандартным процедурам ввода/вывода автоматически проверяются на предмет ошибки, и если ошибка возникает, возбуждается исключение (или программа завершается, если исключение не обработано). Эту автоматическую проверку можно включить или отключить, используя директивы компилятору {$I+} и {$I-}. При выключенной проверке исключение не возбуждается, и чтобы проверить результат операции ввода/вывода следует вызвать стандартную функцию IOResult. Этот вызов очистит флаг ошибки. Если его не сделать, то следующая операция ввода/вывода закончиться с ошибкой.
Два способа безопасной работы с файлами.
Использование директив компилятора для отключения автоматической реакции на ошибки при открытии файла. | Использование механизма структурированной обработки исключений Более современный способ |
1) Объявить файловую переменную var f: TextFile; 2) Перед использованием 2а) Связать файловую переменную с файлом Begin …… AssignFile(f,’file.txt’); 2б) Открыть файл одним из способов, отключив автоматическую реакцию на ошибки ввода/вывода {$I-} Reset(f); {$I+} // только для чтения {$I-} Rewrite(f); {$I+} { для перезаписи = создание + запись} {$I-} Append(f); {$I+} { для дозаписи в конец существующего текстового файла} 2в) Тут же организовать свою проверку кода ошибки. Если IOResult=0, то ошибок нет, иначе можно, например, выдать сообщение и завершить программу. if IOResult <> 0 then begin writeln(‘Ошибка при открытии файла file.txt’); Readln; halt; // задержка и выход end; 3) Если ошибки нет, можно работать с файлом Read(f, ……); Readln(f, ……); Write(f, ……); Writeln(f, ……); Для каждого оператора (а не для целого блока операторов как при обработке исключений) опять же желательно проверить безошибочность его работы, например: {$I-} Readln(f, N); {$I+} if IOResult <> 0 then begin writeln(‘Ошибка при чтении значения для N’); writeln(‘Возможно введено не число?’); CloseFile(f); Readln; halt; // задержка и выход end; 4) Сразу же после окончания работы c файлом можно его закрыть CloseFile(f); …….. End. | 1) Объявить файловую переменную var f: TextFile; 2) Перед использованием 2а) Связать файловую переменную с файлом Begin …… AssignFile(f,’file.txt’); 2б) Открыть файл одним из способов в блоке try Try {попытаемся открыть} Reset(f); // только для чтения Rewrite(f); // для перезаписи = создание + запись Append(f); { для дозаписи в конец существующего текстового файла} 3) Тут же открыть блоки Try, внутри которых можно работать с файлом Try {чтобы закрыть в любом случае} Try {пытаемся прочитать/записать} Read(f, ……); Readln(f, ……); // для чтения из файла Write(f, ……); Writeln(f, ……); // для записи в файл 4) В конце программы завершить все блоки Try. Блок Finally выполняется в любом случае: и при возникновении ошибки, и при ее отсутствии; блок Except – только когда ошибка после Try. Except {при чтении/записи – третий Try} Writeln(‘Ошибка при работе с файлом file.txt’); Readln; halt; End; End; Finally {обязательно закрыть – второй Try} CloseFile(f); End; Except {при открытии файла – первый Try} On EInOutError do Begin Writeln(‘Ошибка при открытии файла file.txt’); Readln; halt; End; End; End. Блоки Try … Finally и Try … Except могут вкладывать друг в друга ЦЕЛИКОМ! |
Пример программы с обработкой ошибки открытия файла
Задача. В заданном целочисленном одномерном массиве A из n элементов найти индексы всех отрицательных элементов (массив B из m элементов)
Использование директив компилятора для отключения автоматической реакции на ошибки при открытии файла. | Использование механизма структурированной обработки исключений. Результат заметен только при запуске exe-файла либо отключении автоматической остановки при возникновении исключительной ситуации! |
Program prov1; {$APPTYPE CONSOLE} var A: array [1..20] of real; B: array [1..20] of byte; n, m, i: byte; // 0..255 fin, fout: TextFile; Begin {ввод исходных данных} AssignFile(fin,'in_file.txt'); {$I-} Reset(fin); {$I+} if IOResult <> 0 then begin writeln('Ошибка открытия файла in_file.txt'); Readln; halt; end; Readln(fin); Readln(fin); //пропуск первых двух строк Readln(fin, n); {ввод n} Readln(fin); //пропуск четвертой строки for i:=1 to n do {ввод элементов массива A} read(fin, A[i]); CloseFile(fin); {вывод исходных данных} AssignFile(fout, 'out_file.txt'); {$I-} Rewrite(fout); {$I+} if IOResult <> 0 then begin writeln('Ошибка создания файла out_file.txt'); Readln; halt; end; Writeln(fout, 'Дан массив A из ', n,' элементов:'); for i:=1 to n do {вывод элементов массива A} write(fout, A[i]:4:1, ' '); writeln(fout); {решение} m:=0; for i:=1 to n do if A[i]<0 then begin inc(m); B[m]:=i; end; {вывод результатов} if m<1 then writeln(fout, 'Отрицательных элементов в массиве A нет') else begin writeln(fout, 'Результат - массив P:'); for i:=1 to m do {вывод элементов массива B} write(fout, B[i], ' '); writeln(fout); end; CloseFile(fout); end. | Program prov2; {$APPTYPE CONSOLE} uses SysUtils; {нужен! там EInOutError} var A: array [1..20] of real; B: array [1..20] of byte; n, m, i: byte; // 0..255 fin,fout: TextFile; Begin AssignFile(fin,'in_file.txt'); Try Reset(fin); {ввод исходных данных} Readln(fin); Readln(fin); //пропуск строк readln(fin, n); {ввод n} Readln(fin); //пропуск строки for i:=1 to n do {ввод элементов массива A} read(fin, A[i]); CloseFile(fin); AssignFile(fout, 'out_file.txt'); Try Rewrite(fout); {вывод исходных данных} Writeln(fout, 'Дан массив A из ',n,' элементов:'); for i:=1 to n do write(fout, A[i]:4:1,' '); writeln(fout); m:=0; {решение задачи} for i:=1 to n do if A[i]<0 then begin inc(m); B[m]:=i end; if m>0 then {вывод результатов} begin writeln(fout, 'Результат - массив B:'); for i:=1 to m do write(fout, B[i], ' '); writeln(fout); end else writeln(fout, 'Отриц. элементов в массиве A нет'); CloseFile(fout); Except On EInOutError do Begin Writeln('Ошибка создания файла out_file.txt'); Readln; halt; End Else Begin Writeln('Другие ошибки… после послед. Try '); Readln; halt; End; End; Except Writeln('Ошибка открытия файла in_file.txt'); Writeln('Либо ввода (некорректные данные)'); Readln; halt; End; end. |
Файл in_file.txt | Файл out_file.txt создается программой |
Данные для задачи Количество 10 Элементы 5 -6 7 1 -2 8 4 -3 9 -5 | Дан массив A из 10 элементов: 5.0 -6.0 7.0 1.0 -2.0 8.0 4.0 -3.0 9.0 -5.0 Результат - массив B: 2 5 8 10 |
С обработкой ошибок не только создания, но и чтения/записи:
Program prov3;
{$APPTYPE CONSOLE}
uses SysUtils;
var
A: array [1..20] of real;
B: array [1..20] of byte;
n, m, i: byte; // 0..255
fin,fout: TextFile;
Begin
AssignFile(fin,'in_file.txt');
Try
Reset(fin);
Try
Try
{ввод исходных данных}
Readln(fin); Readln(fin); //пропуск строк
readln(fin, n); {ввод n}
Readln(fin); //пропуск строки
for i:=1 to n do {ввод элементов массива A}
read(fin, A[i]);
{вывод исходных данных}
AssignFile(fout, 'out_file.txt');
Try
Rewrite(fout);
Try
Try
Writeln(fout, 'Дан массив A из ',n,' элементов:');
for i:=1 to n do write(fout, A[i]:4:1,' '); writeln(fout);
Try
m:=0; {решение задачи}
for i:=1 to n do
if A[i]<0 then begin inc(m); B[m]:=i end;
Except
Writeln(fout, 'Возникла ошибка в вычислениях при поиске решения');
End;
if m>0 then {вывод результатов}
begin
writeln(fout, 'Результат - массив B:'); for i:=1 to m do write(fout, B[i], ' '); writeln(fout);
end
else writeln(fout, 'Отриц. элементов в массиве A нет');
Except
Writeln('Ошибка вывода в файл out_file.txt'); Readln; halt;
End;
Finally
CloseFile(fout);
End;
Except
Writeln('Ошибка открытия/создания файла out_file.txt'); Readln; halt;
End;
Except
Writeln('Ошибка ввода из in_file.txt'); Readln; halt;
End;
Finally
CloseFile(fin);
End;
Except
Writeln('Ошибка открытия файла in_file.txt'); Readln; halt;
End;
end.
Методом обработки исключений можно пользоваться не только в сфере работы с файлами, но и при вычислении выражений. Например, деление на 0:
Program prov4;
{$APPTYPE CONSOLE}
uses SysUtils; {нужен! там EDivByZero и EZeroDivide}
var
a: real;
b, c: integer;
Begin
write('a='); readln(a);
write('b='); readln(b);
write('c='); readln(c);
Try {попытаемся }
writeln(a:5:2,' / ',b,' = ',(a/b):5:2);
writeln(b,' / ',c,' = ', (b/c):5:2);
writeln(c, ' div 0 =', c div (b-b));
Except {возникли ошибки!}
On EZeroDivide do
Writeln('Вещественное число на ноль делить (/0) нельзя!');
On EDivByZero do
Writeln('Целое число на ноль делить (div 0) нельзя!');
Else
Writeln('Другие ошибки');
End;
readln;
End.
Тесты
№ | Смысл | Исходные данные | Ожидаемый результат |
1 | Ошибка при первом же делении | a=2, b=0, c=2 | Нельзя /0 |
2 | Ошибка при втором делении | a=2, b=1, c=0 | 2/1=2 и Нельзя /0 |
3 | Ошибка только при последнем делении | a=2, b=1, c=2 | 2/1=2 и 1/2=0.5 но Нельзя 2 div 0 |
Результат обработки исключений виден только при запуске exe-файла.
При отладке приложения в среде Borland Delphi, обработкой исключений занимается сам Delphi. Он сообщает вам о возникающих исключениях, хотя эту автоостановку можно и отключить… (см. в конце)
![](images/374631-nomer-46330134.png)
Поскольку выполнение блока операторов прерывается в месте возникновения ошибки,
обрабатывать можно не целый блок сразу, а по отдельности:
Program prov5;
{$APPTYPE CONSOLE}
uses SysUtils; {нужен! там EDivByZero и EZeroDivide}
var
a: real;
b, c: integer;
Begin
write('a='); readln(a);
write('b='); readln(b);
write('c='); readln(c);
Try
writeln(a:5:2,' / 0 = ',(a/(b-b)):5:2);
Except
On EZeroDivide do
Writeln('Вещественное число на ноль делить (/0) нельзя!');
Else Writeln('Ошибка в выражении!');
End;
Try
writeln(b,' / ',c,' = ', b/c:5:1);
Except
Writeln('Ошибка в выражении ', b,' / ',c,'!');
End;
Try
writeln(c, ' div 0 =', c div (b-b));
Except
On EDivByZero do
Writeln('Целое число на ноль делить (div 0) нельзя!');
Else Writeln('Ошибка в выражении!');
End;
readln;
end.
Тесты
№ | Смысл | Исходные данные | Ожидаемый результат |
1 | Ошибка при каждом делении | a=2, b=0, c=2 | Нельзя /0 Ошибка в выражении! Нельзя div 0 |
2 | Ошибка при первом и третьем делении | a=2, b=1, c=2 | Нельзя /0 1 / 2 = 0.5 Нельзя div 0 |
Для отключения/включения автоостановки при возникновении исключительных ситуаций и появления извещения об имени исключения:
- в Delphi 2003-2007 зайдите в меню Tools Options, найдите слева в дереве пункт Debugger Exceptions CodeGear Debuggers Language Exceptions, проверьте по рисунку соответствие флажков справа и одного снизу. Последний (в самом низу окна) говорит о том, надо ли информировать оператора об исключении окном диалога (см. ниже): при возникновении этого диалога надо ответить «Продолжить» (Continue), если ЕСТЬ СВОЯ обработка, либо «Прервать» (Break), если своего обработчика нет.
![](images/374631-nomer-2c86a720.png)
![](images/374631-nomer-61cd27b9.gif)
![](images/374631-nomer-m443d6f2f.png)
- в Delphi 7, используйте меню Tools Debugger Options и закладку Language Exceptions:
![](images/374631-nomer-4e969025.png)
![](images/374631-nomer-61cd27b9.gif)