Файл данных – последовательность (sequence) элементов одинакового типа. Помимо того очевидного факта, что файлы хранятся во внешней памяти (жесткие диски, CD, дискеты), файл отличается от массива двумя вещами:
- число элементов в фале заранее неизвестно;
- одновременно доступен лишь один элемент.
На блок-схемах файловые операции изображаются в виде "бочонка" (Рис. 13.1). Такое обозначение идет с тех пор, как в вычислительной технике применялись магнитные барабаны, действительно похожие на бочонок.
Рис. 17.1. Обозначение операций с файлом на блок-схемах.
Возможно два способа доступак файлу: последовательный и параллельный (Рис. 13.2). Разница между двумя способами доступа такая же, как между магнитофонной кассетой и CD: на кассете (последовательный доступ) что добраться до пятой песни, надо промотать первые четыре, а на СD (прямой доступ) можно "перескочить" сразу на любой нужный трек.
Способ доступа не зависит напрямую от конструкции запоминающего устройства. Разумеется, если информация хранится на кассете с магнитной лентой (такое устройство называется стриммером), то доступ всегда будет последовательным. А вот на жестком диске возможны и последовательный, и параллельный виды доступа.
По содержанию файлы данных делятся на текстовые и двоичные (Рис. 13.3).
Рис. 17.2. виды доступа к файлу.
Рис. 17.3. Текстовые и двоичные файлы.
Как и следует из названия, текстовые файлы можно прочитать непосредственно, а двоичные при выводе на экран выглядят как бессмысленная мешанина символов. Файл, в котором хранится текст, совершенно не обязан быть текстовым. Файлы текстового процессора Word являются двоичными.
Очень важный момент при любой работе с файлами – их буферизация. Если программа будет считывать информацию из файла байт за байтом, то после каждого чтения будет заново выполняться установка магнитных головок в новое положение. В итоге работа с файлом замедлится до безобразия. Чтобы такого ужаса не происходило, файл надо читать и записывать как можно более большими кусками (блоками). Лучше всего, когда размер такого блока кратен размеру блока на носителе информации. На жестких дисках и дискетах размер блока, как правило, кратен 256 байтам. Тогда программа за одну операцию чтения или записи может прочитать или считать 25600 байт или 512000 байт и т.д. Но для работы алгоритма нужен только один текущий элемент файла! А куда девать остальное? Если размер элемента – 1 байт, а мы считали 256 байт, то как быть с оставшимися 255-ю? Ответ прост: положить в буфер.
Буфер – специальная область памяти для временного хранения информации, которой программа обменивается с внешними носителями (Рис. 13.4).
Рис. 17.4. Буферизация ввода-вывода.
Буферизацию надо использовать всегда, при любых файловых операциях. В ряде случаев буферизацию незаметно для программиста выполняет Паскаль, а иногда ее надо делать самостоятельно.
Буфер работает по принципу "первый пришел – первый ушел" (FIFO – First In, First Out). Чаще всего применяется кольцевой буфер – массив, в котором выделены индексы текущего записываемого (in) и считываемого (out) элемента (Рис. 13.5).
Рис. 17.5. Кольцевой буфер.
Кольцевой буфер легко создать в прикладной программе:
CONST BS=10240; { размер буфера } VAR buf:ARRAY[0..BS-1] OF WORD; n,in,out:WORD;
{n – число элементов в буфере } PROCEDURE Put(x:WORD); BEGIN IF n=BS THEN EXIT; INC(n); buf[in]:=x; in:=(in+1) MOD BS; END; PROCEDURE Get(VAR x:WORD); BEGIN IF n=0 THEN EXIT; DEC(n); x:=buf[out]; out:=(out+1) MOD BS; END;
Процедуры Put и Get предназначены соответственно для записи и считывания данных из файла. На самом деле данные сначала заносятся в буфер, а уж потом попадают в файл или в программу.
Буферизация требует непреложного выполнения простого правила: перед закрытием файла его буфер должен быть принудительно сброшен на диск. Делается это так:
FOR I:=in TO out DO Write(f,buf[I]); Close(f)
Несброшенный буфер приведет к потере "хвоста" файла.