#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, основанный на той же концепции.