| {в переменной размером 4K) }

| Reset( ft ); {открытие файла }

| Read( ft,...) {операции ввода - все как обычно }

| Reset( ft ); { возврат в самое начало файла }

| { буфер no-прежнему в Buf, 4K }

| Прочие действия с файлом ft

| ...

| END.

Рис. 12.2

Будучи однажды установленным для файла ft, буфер не меняет своего места и (или) размера до следующего вызова SetTextBuf или Assign с той же файловой переменной ft.

Переменная, отводимая под буфер, должна быть глобальной или, по крайней мере, существовать до конца работы с данным файлом. В самом деле, если создать конструкцию типа рис. 12.3, то все как будто должно работать, но не будет.

| PROCEDURE GetFileAndOpenIt( VAR f : Text );

| VAR

| Buffer : Array [1..16*1024] of Byte; { буфер }

| FileName : String; { имя файла }

| BEGIN

| ReadLn( FileName ); { считывается имя файла }

| Assign( f, FileName );

| SetTextBuf( f, Buffer ); { назначение буфера }

| Rewrite( f ) { открытие файла f }

| END;

Рис. 12.3

- 234 -

| VAR

| ff : Text;

| BEGIN { основная часть примера }

| GetFileAndOpenIt( ff );

| Write{ ff, ... ); { попытка записи в файл ff }

| { Дальше неважно, что будет. Все равно результат уже }

| { будет неверный. }

| END.

Рис. 12.3 (окончание)

Дело в том, что локальная переменная Buffer (а именно в ней мы размещаем буфер открываемого файла) существует лишь во время выполнения процедуры. После окончания она исчезает, область буфера становится общедоступной и наверняка очень быстро заполнится совершенно «посторонними» значениями, а переданный в вызывающий блок файл f (ff) будет вести себя непредсказуемо. При всем этом не возникнет ни ошибки компиляции, ни ошибки во время счета.

Если размещать буфер в статической переменной, то он «съедает» часть области данных или стека. А они ограничены размером 64K, что вовсе, не так много. Выгоднее было бы размещать буфер в динамической памяти (куче). Для этого надо объявить указатель на место буфера в куче (рис. 12.4).

| VAR

| ft : Text; { файл типа текст }

| PBuf : Pointer; { ссылка на буфер }

| CONST

| BufSize=1024; { размер буфера }

| BEGIN

| Assign( ft, 'TEXTFILE.DOC' );

| GetMem( PBuf, BufSize); { в памяти отводится }

| { блок размером с буфер }

| SetTextBuf( ft, PBuf^,BufSize ); { Задается буфер в }

| { динамической памяти. }

| Reset( ft ); { открытие файла }

| { . . . } { работа с файлом ft }

| Close( ft };

| FreeMem(Pbuf, BufSize); { Буфер удаляется из }

| { памяти (кучи). }

| END.

Рис. 12.4

- 235 -

В этом случае нужно отводить и освобождать память под буфер, а в SetTextBuf обязательно указывать его размер, так как блок памяти с началом в PBuf^ «не знает» своего размера.

В заключение посоветуем выбирать размер буфера кратным 512 байт. Диск читается по секторам и дорожкам, и длина считываемой в одном месте порции информации колеблется от 512 до 4096 байт для гибких и жестких дисков.

12.6.1.2.Процедура Append(VAR f : Text). Эта процедура служит для специального открытия файлов для записи. Она применима только к уже существующим физическим файлам и открывает их для дозаписи, т.е. файл не стирается, как при вызове Rewrite, а подготавливается к записи элемента в конец файла. Если Append применяется к несуществующему файлу, то возникнет ошибка времени счета. Новый файл может быть создан только процедурой Rewrite. Как автоматически выбрать соответствующую процедуру открытия файла — Append или Rewrite, описано в разд. 12.11.

После открытия файла процедурой Append запись в него будет происходить с того места, где находился признак конца файла (код 26). При необходимости поменять текстовый буфер надо сделать это до открытия файла процедурой Append. Вообще говоря, процедура Append, кроме способа открытия файла (с конца), ничем не отличается от процедуры Rewrite.

Перейти на страницу:

Поиск

Похожие книги