У нас: 141825 рефератів
Щойно додані Реферати Тор 100
Скористайтеся пошуком, наприклад Реферат        Грубий пошук Точний пошук
Вхід в абонемент


яті програми. Оскільки змінні розташовуються там у порядку означення, першими "жертвами" в даному разі стануть змінні blsz, numbl, numblre. Вони мають тип Longint і займають по 4 байти, тому за виконання blockread(f, inbuf, 26, numblre) буде зіпсована лише перша з них, за blockread(f, inbuf, 27, numblre) – перші дві тощо. Отже, треба бути особливо уважним при записі виклику.

Якщо блок, або "зовнішній буфер" не заповнюється до кінця, то кількість блоків, реально прочитаних, буде меншою від заданої кількості. Таким чином, для запобігання неприємностей треба забезпечити, щоб розмір файла ділився на розмір блока. Оскільки розмір блока насправді не впливає на швидкість читання, найкраще надавати йому значення 1. Тоді проблем не буде за будь-якого розміру файла.

Зрозуміло, що коли обробляється файл записів фіксованого розміру, то цей розмір можна задавати і для блока. Наприклад, записи типу

Student=record

Sname, Name : string[20];

Ball : real

end

мають розмір 21+21+6=48 (байтів). Саме це значення повертається з виклику функції

SizeOf(Student).

І взагалі, з виклику вигляду SizeOf(ім’ я-типу) повертається кількість байтів, що займаються значеннями цього типу, наприклад,

SizeOf(char)=1, SizeOf(integer)=2

тощо. Отже, файл f записів типу Student можна відкрити викликом

ReSet(f, SizeOf(Student)).

Після цього виклик вигляду

BlockRead(f, Buf, n, nreal)

задає читання n блоків по 48 байтів у пам’ ять змінної Buf.

Головну роль у швидкості читання безтипових файлів відіграє розмір "внутрішнього буфера". Чим він більше, тим менше звернень до зовнішнього носія і швидше обробка файла. Але все добре в міру.

Можете перевірити твердження, що за розмірів буфера, кратних 512 байтам і більших 8K байтів, швидкість читання файлів практично стала.

Процедура блочного виведення BLOCKWRITE також має 4 аналогічні параметри. Відмінність її в тім, що дані з "внутрішнього буфера" через блок записуються в кінець файла. Зрозуміло, спочатку для файла треба установити розмір "зовнішнього" буфера викликом вигляду ReWrite(f, m).

Повернемося до задачі копіювання й напишемо програму, виконання якої в сотні (!) разів швидше від програми StupidCopy. У ролі "внутрішнього буфера" виступає масив символів Buf розміром у Bufsz=32K байтів. Спочатку за викликом FileSize визначається розмір вхідного файла в байтах, а потім файл читається в масив порціями по Bufsz байтів. Обробка цього буфера в даному разі полягає в блочному копіюванні у вихідний файл. Остання порція може містити менше, ніж Bufsz байтів – масив заповнюється та переписується в файл не до кінця.

program QuickCop;

const Bufsz=32768;

var f, g : file;

Buf : array[1..Bufsz] of char;

restfil, portion : Longint;

rdin, wrou : word; s : string;

begin

writeln( 'Задайте ім'я файла-джерела:');

readln (s); assign (f , s );

writeln( 'Задайте ім'я цільового файла:');

readln (s); assign (g , s );

reset(f, 1); rewrite(g, 1);

restfil:=filesize(f);

while restfil>0 do

begin

if restfil>Bufsz then portion:=Bufsz

else portion:=restfil;

dec(restfil, portion);

Blockread (f, Buf, portion, rdin);

if rdin<>portion then

begin

writeln('Помилка читання файла'); halt

end;

Blockwrite(g, Buf, portion, wrou);

if wrou<>portion then

begin

writeln('Помилка запису файла'); halt

end;

end;

close(g); close(f);

end.

Два зауваження щодо цієї програми. По-перше, до неї можна додати обчислення часу, який займає обробка файла. Для цього слід задати на початку програми підключення модуля Dos і скористатися його процедурою GETTIME. Слід означити 4 змінні типу Word, наприклад,

th, tm, ts, tms : word.

Можна записати виклик

Gettime(th, tm, ts, tms)

десь на початку тіла програми, наприклад, перед відкриванням файлів. За його виконання змінним присвоюються відповідно години, хвилини, секунди ті мілісекунди від вбудованого в комп’ ютер годинника.

Обробка значень цих змінних залежить від смаків програміста. Наприклад, за ними можна обчислити час у сотих долях секунди. Означимо змінну tim типу longint:

tim:=((th*60+tm)*60+ts)*100+tms div 10;

Наприкінці програми запишемо

gettime(th, tm, ts, tms);

tim:=((th*60 + tm)*60 + ts)*100 + tms div 10 - tim;

writeln('Витрачено часу : ', (tim div 100):1, '.',

(tim mod 100 div 10):1,

(tim mod 100 mod 10):1, ' sec'

)

Тоді друкується час виконання у секундах на зразок 3.62 чи 0.01.

Друге зауваження стосується способу задання імен файлів при виконанні програми. Змушувати користувача набирати їх щоразу на клавіатурі – не найкращий варіант. Система Турбо Паскаль дозволяє задавати імена файлів у командному рядку виклику програми і читати їх звідси за допомогою функції PARAMSTR. Наприклад, якщо виклик програми QuickCop записати у вигляді

QuickCop file.in file.out

то рядок 'file.in' є значенням, що повертається з виклику ParamStr(1), 'file.out' – ParamStr(2). У такому разі зв’ язування файлів можна задати так:

assign(f, ParamStr(1));

assign(g, ParamStr(2)).

І взагалі, нехай словом вважається послідовність символів, відмінних від пропуска. Слова після назви програми в командному рядку є рядками, що повертаються з викликів ParamStr із відповідними номерами. Кількість слів повертається з виклику функції PARAMCOUNT (без аргументів).

Отже, якщо користувач програми QuickCop не задав імена файлів у командному рядку, можна примусити його задати їх з клавіатури, написавши на початку програми щось на зразок:

case ParamCount of

0: begin

writeln('Задайте ім'я вхідного файла');

readln(s); assign(f, s);

writeln('Задайте ім'я цільового файла');

readln(s); assign(g, s);

end;

1: begin

assign(f, ParamStr(1));

writeln('Задайте ім'я цільового файла');

readln(s); assign(g, s);

end

else

begin

assign(f, ParamStr(1)); assign(g, ParamStr(2));

end

end.


Сторінки: 1 2 3 4