type
TEncodedStream = class (TFileStream)
private
FKey: Char;
public
constructor Create(const FileName: string; Mode: Word);
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
property Key: Char read FKey write FKey;
end;
Значение ключа просто добавляется к каждому записываемому в файл байту. В процессе чтения происходит декодирование: значение ключа вычитается из читаемых байтов. Приведу полный код методов Read и Write, в которых интенсивно используются указатели.
constructor TEncodedStream.Create(const FileName: string; Mode: Word);
begin
inherited Create (FileName, Mode);
FKey := 'A'; // по умолчанию
end;
function TEncodedStream.Write(const Buffer; Count: Longint): Longint;
var
pBuf, pEnc: PChar;
I, EncVal: Integer;
begin
// выделение памяти для закодированного буфера
GetMem (pEnc, Count);
try
// буфер используется в виде массива символов
pBuf := PChar (@Buffer);
// для каждого символа в буфере
for I := 0 to Count - 1 do
begin
// закодировать значение и сохранить его
EncVal := ( Ord (pBuf[I]) + Ord(Key) ) mod 256;
pEnc [I] := Chr (EncVal);
end;
// записать закодированный буфер в файл
Result := inherited Write (pEnc^, Count);
finally
FreeMem (pEnc, Count);
end;
end;
function TEncodedStream.Read(var Buffer; Count: Longint): Longint;
var
pBuf, pEnc: PChar;
I, CountRead, EncVal: Integer;
begin
// выделение памяти для закодированного буфера
GetMem (pEnc, Count);
try
// чтение закодированного буфера из файла
CountRead := inherited Read (pEnc^, Count);
// использовать буфер вывода в качестве строки
pBuf := PChar (@Buffer);
// для каждого реально прочитанного символа
for I := 0 to CountRead - 1 do
begin
// декодировать значение и сохранить его
EncVal := ( Ord (pEnc[I]) - Ord(Key) ) mod 256;
pBuf [I] := Chr (EncVal);
end;
finally
FreeMem (pEnc, Count);
end;
// вернуть количество прочитанных символов
Result := CountRead;
end;
Комментарии помогут вам разобраться в этом достаточно сложном коде. Теперь, когда у нас есть кодирующий поток, мы можем использовать его в демонстрационной программе под названием EncDemo. На форме этой программы располагается два компонента Memo и три кнопки. При щелчке на первой кнопке в первый компонент Memo загружается обычный текстовый файл. Вторая кнопка записывает текст, содержащийся в первом компоненте Memo, в файл в закодированном виде. Наконец, последняя кнопка загружает содержимое этого файла во второй компонент Memo в декодированном виде. В данном примере я попытался загрузить содержимое закодированного файла в первый компонент Memo в виде обычного текста, и конечно же, отображаемый в этом компоненте текст невозможно прочитать.