Практика
Потоковая передача массива разнородных данных

:: Меню ::
:: На главную ::
:: FAQ ::
:: Заметки ::
:: Практика ::
:: Win API ::
:: Проекты ::
:: Скачать ::
:: Секреты ::
:: Ссылки ::

:: Сервис ::
:: Написать ::

:: 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, и добавляющий поддержку типов данных, специфичных для базы данных.

.: Пример к данной статье :.


При использовании материала - ссылка на сайт обязательна