Наш шпионский проект по шифрованию файла подвигается к финишу. Ступим завершающий шаг: освоим запись в текстовый файл.

Запись в текстовый файл

Порядок записи в текстовый файл схож с его чтением, судите сами:

• для доступа к файлу используют файловую переменную типа TEXT;

• файловую переменную надо связать с файлом процедурой Assign;

• по окончании записи файл закрывают процедурой Close.

Вот схема, где отражены четыре этапа записи в файл (рис. 56).

Рис.56 – Четыре этапа записи в файл

Как видите, запись в файл отличается от чтения вторым и третьим этапами, ими и займемся.

Итак, после привязки файла процедурой Assign, файл открывают для записи процедурой Rewrite – «перезапись».

      Rewrite(F);

Тут находим первое отличие: если для чтения требуемый файл должен существовать, то для записи этого не нужно. Если файла ещё нет, будет создан новый пустой файл. А при наличии файла он будет очищен, и вся информация в нём сотрется, как мел с доски. Будьте внимательны, иначе лишитесь нужной информации!

В открытый таким образом файл можно «печатать» нужные нам строки. Как? Вы уже знаете – процедурой Writeln. А что указать первым параметром? Правильно, – файловую переменную, вот так:

      Writeln(F, S); { F – переменная типа TEXT, S – строковая }

Каждый вызов такой процедуры добавляет в конец файла очередную строку с разделителями. В отличие от чтения, где надо следить за достижением конца файла, при записи вы ограничены лишь объёмом винчестера и здравым смыслом (в большей степени последним).

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

Пример записи в файл

Рассмотрим небольшой пример: заполнение файла числами от 1 до 10.

{ P_26_1 }

var F: text;       { файловая переменная }

      k: integer;

begin

      Assign(F, 'P_26_1.txt'); { назначаем имя файла }

      Rewrite(F);       { открываем файл для записи }

      for k:=1 to 10 do       { записать 10 строк с числами }

      Writeln(F, k);

      Close(F);       { закрываем файл }

end.

Есть вопросы? Запустите программу и проверьте, работает ли она. Запустили? Теперь отыщите в папке с программой файл «P_26_1.TXT» и откройте его любым редактором. Уверен, что вы обнаружите в нём столбик из десяти чисел.

Завершение шпионского проекта

Подойдя к финалу нашего проекта, мы научились: 1) шифровать отдельную строку, 2) читать строки из файла и 3) записывать строки в файл. Пора соединить все это: читая строки исходного файла, будем шифровать их, и записывать в другой файл, – так будет работать наша программа.

Прежде всего договоримся об именах файлов. Назначив зашифрованному файлу постоянное имя, например «CRYPT.TXT», мы избавим себя от ввода его имени с клавиатуры. Вводить мы будем либо имя исходного файла – при шифровании, либо имя конечного файла – при расшифровке. Обозначим эти неизвестные нам имена файлов как X1 и X2, и тогда схема обработки файлов будет такой.

Рис. 57 – Схема именования файлов при шифровании и расшифровке

С учетом этих договоренностей составим блок-схему программы (рис. 58).

Рис.58 – Блок-схема программы шифрования/расшифровки

Основную работу поручим процедуре шифрования-расшифровки, блок-схема которой показана на рис. 59. В неё передаём два параметра: имя обрабатываемого файла и код операции (зашифровать или расшифровать).

Рис.59 – Блок-схема процедуры шифрования-расшифровки

Теперь мы готовы смастерить шпионскую программу. Может быть, сами справитесь? По крайней мере, попытайтесь. Функции и процедуры шифрования символов и строк возьмите из программы «P_24_1». Написав свой вариант, сравните с представленным ниже.

{ P_26_2 – шифрование и расшифровка файлов }

const CKey = 2; { Ключ Цезаря }

      { Шифрование одного символа }

function Encrypt(arg: char): char;

var x: integer;

begin

Encrypt:=arg;

if Ord(arg)>=32 then begin { управляющие символы не трогаем! }

x:= Ord(arg)+ CKey;

if x>255 then x:= x-256+32;

Encrypt:= Char(x);

end;

end;

      { Расшифровка одного символа }

function Decrypt(arg: char): char;

var x: integer;

begin

Decrypt:=arg;

if Ord(arg)>=32 then begin { управляющие символы не трогаем! }

x:= Ord(arg)- CKey;

if x<32 then x:= x+256-32;

Decrypt:= Char(x);

end;

end;

      { Шифрование строки }

procedure EncryptStr(var arg: string);

var k: integer;

begin

      for k:=1 to Length(arg) do arg[k]:= Encrypt(arg[k]);

end;

      { Расшифровка строки }

procedure DecryptStr(var arg: string);

var k: integer;

begin

      for k:=1 to Length(arg) do arg[k]:= Decrypt(arg[k]);

end;

      {----- Процедура шифрования-расшифровка файла -----}

procedure CryptFile(const aFile: string; aOper: boolean);

const CFixName='Crypt.txt'; { фиксированное имя файла }

var FileIn: text; { входной файл для чтения }

      FileOut: text; { выходной файл для записи }

      S: string;

begin

      if aOper then begin       { если шифровать }

      Assign(FileIn, aFile);

      Assign(FileOut, CFixName);

      end else begin       { если расшифровать }

      Assign(FileIn, CFixName);

      Assign(FileOut, aFile);

      end;

      Reset(FileIn);    { открыть входной файл для чтения }

      Rewrite(FileOut); { открыть выходной файл для записи }

      while not Eof(FileIn) do begin

      { пока не закончился входной файл }

      Readln(FileIn, S);       { читать очередную строку из файла }

      if aOper

      then EncryptStr(S) { зашифровать }

      else DecryptStr(S); { расшифровать }

      Writeln(FileOut, S);       { записать в выходной файл }

      end;

      { закрыть оба файла }

      Close(FileIn); Close(FileOut);

end;

      {----- Главная программа -----}

var S: string;

      Oper: boolean; { TRUE – шифровать, FALSE – расшифровать}

begin

      Write('Укажите операцию (1 – шифровать, иначе – расшифровать):');

      Readln(S);

      Oper:= S='1'; { Oper=TRUE если S='1' }

      if Oper

      then Write('Введите имя шифруемого файла: ')

      else Write('Введите имя расшифрованного файла: ');

      Readln(S);

      CryptFile(S, Oper); { Вызов процедуры шифрования–расшифровки }

      Write('OK, нажмите Enter'); Readln;

end.

Пространные пояснения излишни. Признак выполняемой операции формируется в булевой переменной Oper в третьей строке главной программы по цифре, введенной в переменную S. Значение Oper=TRUE влечет зашифровку файла, а FALSE — расшифровку. Затем в переменную S вводится имя обрабатываемого файла. В конце концов, вызывается процедура CryptFile с передачей в неё двух параметров: имени файла и признака выполняемой операции (aFile и aOper). Приставка «a» в начале имен этих параметров (префикс) помогает при чтении программы отличить параметр от других переменных.

Полюбуйтесь, во что превратила эта программа один из файлов на Паскале (приведен небольшой фрагмент).

}"Rtqi2420rcu"

xct"Ocp"<"uvtkpi=

}///"░гьёднзпкз"▒т░шзжхтэ"///

rtqegfwtg"Rcwug=

dgikp

"""""Ytkvgnp*)Пвиокфз"Gpvgt<)+=""Tgcfnp=

Как говорится, родная мама не узнает! Все, что попадает в «мясорубку» нашего шифровальщика, обращается в фарш. Однако последующая расшифровка «перемолотого» файла в точности восстановила его.

Примененный нами метод шифрования не так уж крут, опытный взломщик легко раскроет его. Но фундамент заложен, и когда-нибудь вы придумаете изощренные методы шифрования. Например, ключ шифра можно сделать переменным и зависящим от номера символа в строке или файле. Подумайте над этим. Если же вы намерены заняться криптографией всерьез, изучайте математику! Для программиста это наука номер один.

Итоги

• Для записи в текстовый файл, как и для чтения, требуется файловая переменная типа TEXT.

• Перед записью выполняют два действия: связывание переменной с файлом процедурой Assign и открытие файла для записи процедурой Rewrite.

• Вызов процедуры Rewrite либо создаёт новый файл, либо очищает существующий (вся бывшая в нём информация теряется!).

• Запись отдельных строк в файл выполняют процедурой Writeln, первым параметром здесь указывают файловую переменную.

• По окончании записи файл закрывают процедурой Close, – это гарантирует сохранение данных на диске.

А слабо?

А) Программа создает файл, печатает в него несколько строк с числами, а затем выводит этот файл на экран. Воспользуйтесь одной файловой переменной.

Б) Программа для нумерации строк файла. Строки исходного файла должны копироваться в конечный файл с добавлением перед каждой строкой её номера, например:

Исходный файл:

В лесу родилась елочка,

В лесу она росла.

Зимой и летом стройная,

Зеленая была.

Конечный файл:

1

В лесу родилась елочка,

2

В лесу она росла.

3

Зимой и летом стройная,

4

Зеленая была.

В) Скопировать один файл в другой:

• с перестановкой местами четных и нечетных строк;

• с перестановкой строк в обратном порядке (см. условие задачи «Е» к 25-й главе).

Г) Для передачи по интернету секретного текстового файла разбейте его на два других: в первый запишите нечетные строки исходного файла, а во второй – четные. Напишите для этого программу, или слабо?

Д) Создайте программу для объединения двух файлов (см. условие предыдущей задачи). Из первого составьте нечетные строки конечного файла, а из второго – четные.