:: MVP ::
|
|
:: RSS ::
|
|
|
Конвертация данных — преобразование данных из одного формата в другой, обычно с сохранением основного
логически-структурного содержания информации. Существует множество путей, которые могут использоваться
для преобразования данных в рамках компьютерной среды (программы), один из которых будет рассмотрен в
данной статье. Речь пойдет о классе TBitConverter, реализованном в модуле System.Types, представляющем
собой конвертер между нативными типами данных Delphi и массиваом байтов.
Две основные функции класса, это: From - преобразует значение в нативном типе Delphi в массив байтов,
и InTo - преобразует массив байтов в нативный тип Delphi. Для обеих функций существует небезопасная версия
(UnsafeFrom, UnsafeInTo), которая не проверяет правильность указанного смещения. Небезопасные функции работают
быстрее, чем их безопасные аналоги, но использовать их стоит только в том случае, если вы абсолютно уверены,
что значение смещения, которое вы передаете функции, не ниже 0 или не настолько велико, что вместе с размером
указанного типа T, выходит за пределы целевого массива байтов.
Представление данных в виде массива байтов очень удобно для организации процесса обмена данными с помощью,
например, потоков. Рассмотрим небольшой пример.
uses
System.Types;
type
TArrVar = array of Variant;
TArrVarHelper = record Helper for TArrVar
function ToString: string;
end;
function ArrToStream(av: TArrVar): TBytesStream;
var
i: Integer;
Buf: TBytes;
begin
Result := TBytesStream.Create;
SetLength(Buf, SizeOf(Variant));
for i := Low(av) to High(av) do
begin
TBitConverter.UnsafeFrom<Variant>(av[i], Buf);
Result.WriteBuffer(Buf, SizeOf(Variant));
end;
end;
{$DEFINE REVERSE_ARR}
function ArrFromStream(bs: TBytesStream): TArrVar;
var
Buf: TBytes;
{$IFDEF REVERSE_ARR}
Base: Integer;
{$ENDIF}
begin
bs.Position := 0;
SetLength(Result, bs.Size div SizeOf(Variant));
SetLength(Buf, SizeOf(Variant));
{$IFDEF REVERSE_ARR}
Base := bs.Size div SizeOf(Variant) - 1;
{$ENDIF}
while bs.Position < bs.Size do
begin
bs.ReadBuffer(Buf, SizeOf(Variant));
Result[{$IFDEF REVERSE_ARR}Base -{$ENDIF}(bs.Position div SizeOf(Variant) - 1)] :=
TBitConverter.UnsafeInTo<Variant>(Buf);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
x: TArrVar;
bs: TBytesStream;
begin
bs := ArrToStream(['Я','н','е','м','и','н','е','ж','е','н']);
x := ArrFromStream(bs);
bs.Free;
ShowMessage(x.ToString);
end;
{ TArrIntHelper }
function TArrVarHelper.ToString: string;
var
i: Variant;
begin
Result := '';
for i in Self do
Result := Result + VarToStr(i) + ',';
Result := Result.Remove(Length(Result)-1);
end;
|
Массив вариантных значений преобразовывается в поток (ArrToStream), который может быть передан куда угодно.
Принимающая сторона (ArrFromStream) может просто восстановить информацию в ее исходном виде (с отключенной
директивой {.$DEFINE REVERSE_ARR} в примере), а может, в случае необходимости, ее модифицировать (например,
инвертировать, если в примере включена директива {$DEFINE REVERSE_ARR}).
Корректность работы данного метода проверим на примере палиндрома-оборотня "Я нем и нежен". Замечательный
результат, полученный весьма несложным путем! В заключение остается добавить, что у класса TBitConverter есть
потомок - TDBBitConverter, реализованный в модуле Data.DB, и добавляющий поддержку типов данных, специфичных для
базы данных.
.: Пример к данной статье :.
|
При использовании материала - ссылка на сайт обязательна
|
|