Практикуемся в использовании потоков: TFileStream, TBase64EncodingStream, TBase64DecodingStream. Программа кодирует файлы (бинарные, в частности - картинки) используя кодировку MIME - base64. Полученный код состоит только из 64 текстовых символов: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ и может быть передан по каналам, пропускающим только этот алфавит (например, некоторые протоколы, используемые Интернетом). Этот код можно использовать как данные в SQL-запросах и таким образом хранить бинарные данные (в закодированном текстовом виде) в базах данных. Расплата за это - увеличение объема данных на 33%.
Кроме этого, программа демонстрирует копирование файлов - с использованием потоков TFileStream. Для тестирования правильности кодировки есть процедура, создающая тестовый бинарный файл, содержащий заданное количество случайных байт (0..255)
Остались нерешенные проблемы (в основном русификация):{ В Лазарусе постепенно привыкаешь к тому, что поиск описаний через Ctrl-щелчок при наведении курсора на идентификатор не хуже, чем справка Делфи (если понимать Object Pascal) } unit unmain; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls, Menus, base64; type { TForm1 } TForm1 = class(TForm) MainMenu1: TMainMenu; Memo1: TMemo; MenuItem1: TMenuItem; decode: TMenuItem; randfile: TMenuItem; Quit: TMenuItem; SD1: TSaveDialog; b64_encode: TMenuItem; CopyStream: TMenuItem; OD1: TOpenDialog; procedure CopyStreamClick(Sender: TObject); procedure decodeClick(Sender: TObject); procedure QuitClick(Sender: TObject); procedure b64_encodeClick(Sender: TObject); procedure randfileClick(Sender: TObject); private { private declarations } public { public declarations } end; var Form1: TForm1; implementation { TForm1 } procedure TForm1.CopyStreamClick(Sender: TObject); var InStream, OutStream: TFileStream; len, CountIn, CountOut : integer; bur: ansistring; FNameOD1,FNameSD1: ansistring; begin Memo1.Clear; OD1.Title:= AnsiToUTF8('Выберите файл для копирования'); SD1.Title:= AnsiToUTF8('Задайте имя для сохраняемого файла'); if (OD1.Execute and SD1.Execute) then begin FNameOD1:= UTF8ToAnsi(OD1.FileName); FNameSD1:= UTF8ToAnsi(SD1.FileName); InStream := TFileStream.Create(FNameOD1, fmOPenREad); OutStream:= TFileStream.Create(FNameSD1, fmCreate); len:= InStream.Size; SetLength(bur,len); countIn := InStream.Read(bur[1],Len); countOut:= OutStream.Write(bur[1],Len); Memo1.Text:= AnsiToUTF8(bur); Memo1.Lines.Append('_____________________________'); Memo1.Lines.Append (AnsiToUTF8('Прочтено: ')+IntToStr(countIn)+AnsiToUTF8(' из ') + IntToStr(len) + AnsiToUTF8(' байт текста') ); Memo1.Lines.Append (AnsiToUTF8('Записано: ')+IntToStr(countOut)+AnsiToUTF8(' из ') + IntToStr(countIn) + AnsiToUTF8(' байт текста')); InStream.Free; OutStream.Free; end; end; procedure TForm1.decodeClick(Sender: TObject); var ii,Size,Size2: integer; b64decoder: TBase64DecodingStream; InStream, OutStream: TFileStream; Arba: array of byte; FNam,FNam2: string; IsEnd: boolean; begin SD1.Title:= AnsiToUTF8('Декодируем OutFile.bbb Задайте имя результата'); if not SD1.Execute then exit; FNam2:= SD1.FileName; OutStream:= TFileStream.Create(FNam2, fmCreate ); isend:= false; FNam:= 'OutFile.bbb'; InStream := TFileStream.Create(FNam, fmOPenREad); Size:= InStream.Size; SetLength(arba,Size); b64decoder:= TBase64DecodingStream.Create(InStream,bdmMIME); ii:= -1; memo1.Clear; while not IsEnd do try inc(ii); arba[ii]:= b64decoder.ReadByte; except on e: EStreamError do IsEnd := True; end; Size2:= ii+1; OutStream.Write(arba[0], Size2-1); // Почему-то нужно недописывать 1 байт ? b64decoder.Free; InStream.Free; OutStream.Free; end; procedure TForm1.QuitClick(Sender: TObject); begin Application.Terminate; end; procedure TForm1.b64_encodeClick(Sender: TObject); var ii,maxa: integer; b64encoder: TBase64EncodingStream; InStream, OutStream: TFileStream; FNam, InFile: string; arba: array of byte; begin OD1.Title:= AnsiToUTF8('Выберите файл. Результат: OutFile.bbb'); if not OD1.Execute then exit; InFile:= OD1.FileName; InStream:= TFileStream.Create(InFile, fmOpenRead); maxa:= InStream.Size; SetLength(arba,maxa); InStream.Read(arba[0], maxa); FNam:= 'OutFile.bbb'; OutStream:= TFileStream.Create(FNam, fmCreate); b64encoder:= TBase64EncodingStream.Create(OutStream); for ii:=1 to maxa do b64encoder.WriteByte(Arba[ii-1]); arba:= nil; b64encoder.Free; OutStream.Free; InStream.Free; end; procedure TForm1.randfileClick(Sender: TObject); var OutStream: TFileStream; FSize,ii: integer; bufsi, FNam: string; rndMax: longInt; arabik: array of byte; { Создаем файл для тестирования кодирования-декодирования Сравнивать исходный и декодированный файл на идентичность удобно, например, в Total Commander } begin FNam:= 'TestFile.rnd'; OutStream:= TFileStream.Create(FNam, fmCreate); {function InputBox(const ACaption, APrompt, ADefault : String) : String;} bufsi:= InputBox( AnsiToUTF8('Создаем тестовый файл.'), AnsiToUTF8('Введите размер файла (байт)'),'512'); showmessage(AnsiToUTF8('Результат: файл TestFile.rnd'+#13#10+ '(случайные числа)')); FSize:= StrToInt(bufsi); SetLength(arabik,FSize); rndMax:= 256; for ii:= 1 to FSize do arabik[ii-1]:= random(rndMax); OutStream.Write(arabik[0], FSize); arabik:= nil; OutStream.Free; end; initialization {$I unmain.lrs} end.