Автор: Пользователь скрыл имя, 28 Декабря 2011 в 12:54, реферат
Надо заметить, что физически единой эта область данных вовсе не является: файл обычно состоит из целого набора так называемых кластеров (участков диска фиксированного для операционной системы размера), которые разбросаны по диску тем прихотливее, чем чаще мы стираем и записываем на него информацию.
Вообще, система окажется наиболее производительной, если кластеры файла будут идти не подряд, а с неким постоянным интервалом: пока система "переварит" данные с одного кластера, диск как раз успеет повернуться до другого.
Операторы Write (F, x1, x2, ...) и Writeln (F, x1, x2, ...) записывают в файл F значения переменных x1, x2, ... точно так же, как это делают операторы Write и Writeln для консольного вывода. Аргументы могут иметь любой арифметический тип и для них действуют те же правила форматирования:
При n>0 выравнивание производится по правому краю, при n< 0 - по левому.
Задача: дан массив, содержащий температуру воздуха для каждого часа на каждый день месяца. Вывести эти значения в текстовый файл в виде таблицы, при этом добавить колонку средних температур.
program Example; (***************************** * Задача: дан массив, содержащий температуру воздуха * * для каждого часа на каждый день месяца. Вывести эти * * значения в текстовый файл в виде таблицы, при этом * * добавить среднюю температуру. * ****************************** const MONTHNAME='Июнь'; MINTEMPER=15; MAXTEMPER=36; var OutFile: Text; {файл таблицы} FileName: string; Temper : array [1..31,1..24] of byte; {массив температур} i, j, Sum: integer; (***************************** Процедура заполняет массив температур случайными значениями. Распределение, конечно, получится нереальным, но для иллюстрации этого будет достаточно. ****************************** procedure CountArray; var i, j: integer; begin for i:=1 to 31 do for j:=1 to 24 do
Temper[i,j] := Random(MAXTEMPER-MINTEMPER)+ end; begin {Заполняем массив температур} CountArray; write('Введите имя файла для вывода таблицы '); readln(FileName); Assign(OutFile, FileName); Rewrite(OutFile); {Шапка таблицы} writeln(OutFile,'Температура воздуха на месяц: ',MONTHNAME); for i:=1 to 26 do write(OutFile,'+---'); writeln(OutFile,'+'); write(OutFile,'| |Ср.|'); for i:=1 to 24 do write(OutFile,i:3,'|'); writeln(OutFile); for i:=1 to 26 do write(OutFile,'+---'); writeln(OutFile,'+'); {Вывод значений температуры} for j:=1 to 31 do begin {Сумма дневных температур для вычисления средней} Sum:=0; for i:=1 to 24 do Sum:=Sum+Temper[j,i]; {Выводим среднюю и почасовые температуры} write(OutFile,'|',j:3,'|'); if Sum>0 then write(OutFile, '+',(Sum div 24):2,'|') else write(OutFile, (Sum div 24):3,'|'); for i:=1 to 24 do if Temper[j,i]>0 then
write(OutFile,'+',Temper[j,i]: else
write(OutFile,Temper[j,i]:3,'| writeln(OutFile); end; {Закрываем таблицу и файл} for i:=1 to 26 do write(OutFile,'+---'); writeln(OutFile,'+'); Close(OutFile); end. |
В случае, когда массив температур заполняется случайными числами, мы получим в файле результат вроде этого (приведена левая часть таблицы):
Температура воздуха на месяц: Июнь +---+---+---+---+---+---+---+- | |Ср.| 1| 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14| 15| 16| 17| 18| +---+---+---+---+---+---+---+- | 1|+23|+15|+15|+33|+19|+20|+29| | 2|+24|+18|+21|+24|+20|+32|+20| | 3|+27|+31|+29|+26|+19|+29|+27| ... | 30|+22|+30|+34|+20|+18|+17|+35 | 31|+23|+16|+31|+23|+15|+29|+25 +---+---+---+---+---+---+---+- |
Конечно, такая
таблица никоим образом не соответствует
реальному распределению
Еще одна дополнительная особенность текстовых файлов в Паскале - возможность их дозаписи. При этом файл открывается директивой Append вместо Rewrite. Например, после выполнения фрагмента:
Rewrite (F); writeln (F, 'Куда идем мы с Пятачком -'); Close (F); Append (F); writeln (F, 'Большой-большой секрет.'); Close (F); |
Содержимое файла F будет иметь вид:
Куда идем мы с Пятачком - Большой-большой секрет. |
Ввод-вывод для бестиповых файлов
Буфер - это область памяти, которая выделяется для каждого файла при его открытии.
Мы уже говорили,
что информация, записываемая в файл,
вначале оказывается в буфере
оперативной памяти, а в файл перебрасывается,
только когда весь буфер заполнен.
Точно так же и при чтении из
файла сразу считывается
Например, если
буфер вмещает 64 байта, а программа
запрашивает из файла 4, то в буфер
считается 64 байта из файла, затем 4
первых из них будет передано программе.
Остальные либо передадутся по запросу
позже, либо будут потеряны, если чтение
этого участка файла
Стандартные операторы Reset(F) и Rewrite(F) при открытии бестипового файла устанавливают размер буфера в 128 байт. Но можно задать этот размер программно при помощи операторов Reset (var F: File; BufSize: Word) и Rewrite (var F: File; BufSize: Word). Чем больше размер буфера, тем меньше будет при выполнении программы обращений к диску и значит, тем быстрее будет выполняться программа, поскольку обращение к диску производится гораздо медленнее, чем к памяти.
Однако, если мы считываем информацию небольшими блоками и не последовательно, а напрямую, такое увеличение буфера может даже снизить производительность.
Минимально возможный размер считываемого или записываемого блока - 1 байт, максимальный - 64 килобайта.
Поскольку в бестиповых файлах речь может идти только о работе с отдельными байтами, то считывание и запись информации также производится блоками по несколько байт.
Оператор BlockRead (var F: File; var Where; Count: Word [; var ReadIn: Word]) считывает из бестипового файла F Count емкостей буфера (размер буфера объявлен при открытии файла) и помещает всю считанную информацию в память начиная с адреса Where.
Параметр ReadIn необязателен, в него записывается целое число блоков (буферов), которое действительно считалось в процессе операции. ReadIn удобно использовать для отслеживания ошибок чтения.
Count*Размер_буфера не может превышать 64 килобайта. Это обязательное условие для DOS-программы.
Для записи информации в бестиповой файл используется оператор BlockWrite (var F: File; var Where; Count: Word [; var WriteOut: Word]). Здесь параметр Where указывает на адрес начала буфера в оперативной памяти, откуда берется информация, а необязательный аргумент WriteOut после окончания операции будет содержать действительное количество записанных в файл блоков.
Например:
var {объявляем буфер в виде массива в памяти} Buf : Array [1..10] of integer; F : File; Value : integer; ... Reset(F,16); {открываем бестиповый файл, размер буфера 16 байт} {чтение из файла 32 байт (2*16) и запись по адресу 1 элемента массива} BlockRead (F,Buf,2); {чтение из файла 64 байт и запись по адресу 5 элемента массива} BlockRead (F,Buf[5],4); - чтение в Х 64 байт начиная с 5 элемента |
Рассмотрим задачу: требуется побайтово скопировать один произвольный файл в другой. Программу для решения этой задачи можно составить так:
program Example; (***************************** * Демонстрация работы с нетипизированными файлами и * * использования параметров командной строки. * * Задача: побайтово скопировать один файл в другой. * ****************************** var SrcFile, DestFile: File; {файл-источник и файл-приемник} NumRead, NumWrite: Word; {количество обработанных блоков} Buf: array [1..1024] of Char; {буфер можно задать и так} begin {проверяем количество параметров командной строки} if ParamCount< 3 then begin writeln('Ошибка: недостаточно параметров командной строки.'); exit; end; {открываем оба файла} Assign(SrcFile, ParamStr(2)); {$I-} Reset(SrcFile, 1); {размер буфера 1 байт} {$I+} if IOResult<>0 then begin writeln('Ошибка: невозможно открыть исходный файл.'); exit; end; Assign(DestFile, Param Str(3)); Rewrite(DestFile, 1); {размер буфера тоже 1 байт} {копируем} Writeln('Копирую файл ',ParamStr(2),' в ', FileSize(SrcFile), ' байт...'); repeat BlockRead(SrcFile, Buf, SizeOf(Buf), NumRead); BlockWrite(DestFile, Buf, NumRead, NumWrite); until (NumRead = 0) or (NumWrite <> NumRead); writeln('Копирование завершено.'); Close(SrcFile); Close(DestFile); end. |