Оптимизация олевариантного потока в TStringList

#delphi #com #delphi-xe

#delphi #com #delphi-xe

Вопрос:

Мой сервер возвращает поток строк как олевариантный через вызов COM / DCOM. Этот код хорошо работает для клиента, но, вероятно, может быть улучшен. Подсказки приветствуются.

И в качестве продолжения, что, если сервер вернет олевариантный поток как UTF-8, каков наилучший способ для клиента преобразовать его в unicode?

 procedure TClientToServer.GetText(       mode     : integer;
                                                 const infoText : widestring;
                                                      txt         : TStrings);
var
  size        : integer;
  dataP       : pointer;
  data        : OleVariant;
  strStream   : TStringStream;
begin
  txt.Clear;
  data:= fDComServer.GetData( mode,infoText);
  if VarIsNull(data) then Exit;
  size:= VarArrayHighBound(data,1)   1;
  dataP:= VarArrayLock( data);
  try
    strStream:= TStringStream.Create;
    try
      strStream.Write( dataP^,size);
      strStream.Seek(0,0);
      txt.LoadFromStream( strStream);
    finally
      strStream.Free;
    end;
  finally
    VarArrayUnlock( data);
  end;
end;
  

Редактировать :
Переход на UTF8 означает, что в сети используется меньшая пропускная способность, и я могу повторно использовать процедуры COM / DCOM более или менее неповрежденными при последующей реализации интерфейса протокола http на основе строк UTF8.

Спасибо Дэвиду, что указал мне правильное направление, чтобы немного урезать код.

Вот обновленная процедура :

 procedure TClientToServer.GetText(       mode     : integer;
                                   const infoText : widestring;
                                         txt         : TStrings);
var
  size    : integer;
  dataP   : Pointer;
  data    : OleVariant;
  utf8Str : Utf8String;
begin
  txt.Clear;
  data:= fDComServer.GetData( mode,infoText);
  if VarIsNull(data) then Exit;
  size:= VarArrayHighBound(data,1)   1;
  dataP:= VarArrayLock( data);
  try
    SetString( utf8Str, PAnsiChar(dataP), size);
    txt.Text:= utf8Str;
  finally
    VarArrayUnlock( data);
  end;
end;
  

Ответ №1:

На самом деле вам не нужен поток строк. Вы можете просто вызвать SetString() , чтобы создать строку Delphi, содержащую содержимое dataP , а затем присвоить эту строку txt.Text . Если у вас есть данные в формате UTF8, передайте строку UTF8 в SetString() .

Использование SetString() по-прежнему требует промежуточного выделения буфера, поэтому я думаю, что действительно было бы неплохо иметь TStream потомок, доступный только для чтения, которому вы могли бы передать указатель и размер. Вы могли бы передать этот поток в TStrings.LoadFromStream . Написать такую вещь было бы достаточно просто.

У вас действительно есть проблемы с производительностью? Если нет, то зачем менять ваш текущий подход.

Комментарии:

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

2. @LU RD 200 КБ — это ничего особенного. Поскольку впоследствии вы, вероятно, будете что-то делать с этими данными, это, вероятно, сократит время, которое вы могли бы сэкономить, удалив одно из перераспределений. Но я предполагаю, поскольку только вы знаете, что вы делаете с этим текстом.

3. Производительность, как вы говорите, не будет проблемой. Я постараюсь реализовать ваши предложения.

4. @LU Зачем менять? Я не уверен, что у вас есть настоятельная необходимость в этом.

5. Дэвид, посмотри мой обновленный вопрос. Сервер и клиент теперь отлично работают, используя UTF8. Теперь я собираюсь реализовать дополнительный клиент-серверный интерфейс на основе http, основанный на той же концепции.