Очень важный момент при любой работе с файлами – их буферизация. Если программа будет считывать информацию из файла байт за байтом, то после каждого чтения будет заново выполняться установка магнитных головок в новое положение. В итоге работа с файлом замедлится до безобразия. Чтобы такого ужаса не происходило, файл надо читать и записывать как можно более большими кусками (блоками). Лучше всего, когда размер такого блока кратен размеру блока на носителе информации. На жестких дисках и дискетах размер блока, как правило, кратен 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)
Несброшенный буфер приведет к потере "хвоста" файла.