2013-11-22 2 views
3

Рассмотрим следующий фрагмент кода (в Delphi XE2):Присвоить [массив байт] к варианту без преобразования Unicode

function PrepData(StrVal: string; Base64Val: AnsiString): OleVariant; 
begin 
    Result := VarArrayCreate([0, 1], varVariant); 
    Result[0] := StrVal; 
    Result[1] := Base64Val; 
end; 

Base64Val представляет собой двоичное значение закодировано как Base64 (так что никаких null байтов). (OleVariant) Результат автоматически сортируется и отправляется между клиентским приложением и сервером DataSnap.

Когда я фиксирую трафик с Wireshark, я вижу, что и StrVal, и Base64Val передаются как строки Unicode. Если можно, я бы хотел избежать преобразования Unicode для Base64Val. Я просмотрел все типы Variant и не вижу ничего, кроме varString, который может передавать массив символов.

Я нашел this question, который показывает, как создать вариант массива байтов. Я думаю, что я мог бы использовать эту технику вместо использования AnsiString. Мне любопытно, однако, есть ли другой способ назначить массив не-Unicode символьных данных для Variant без преобразования в строку Unicode?

ответ

4

Реализация Delphi поддерживает сохранение AnsiString и UnicodeString в варианте с использованием пользовательских кодов типа варианта. Этими кодами являются varString и varUString.

Но interop обычно использует стандартные варианты OLE, а строка OLE, varOleStr, кодируется в 16 бит. Это, по-видимому, является причиной вашего наблюдения.

Вам нужно будет поместить данные в виде массива байтов, если вы хотите избежать преобразования в 16-битный текст. Это делает ненулевым кодирование base64. Остановите base64, кодируя полезную нагрузку и отправляйте двоичный файл в массив байтов.

+0

«Эти коды varString и varUString.» - AFAIR, для ShortString. для AnsiString существует varLString // PS: существует также кодировка yEnc, если по какой-либо причине бинарный поток невозможен, а base64 слишком тяжелый –

+0

@ Arioch Nope, это длинные строки –

+0

Получил его работу. Он отправляет двоичные данные через PVarArray, размещенный в OleVariant, без использования Base64. Я отправлю ответ отдельно, включая ссылку на другой ответ Дэвида, где он показал, как выполнять большую часть работы. –

1

Держа с примером в вопросе, это как я сделал его работу (используя код и комментарии из David's answer на другой вопрос, как указано в моем вопросе):

function PrepData(StrVal: string; Data: TBytes): OleVariant; 
var 
    SafeArray: PVarArray; 
begin 
    Result := VarArrayCreate([0, 1], varVariant); 
    Result[0] := StrVal; 
    Result[1] := VarArrayCreate([1, Length(Data)], varByte); 
    SafeArray := VarArrayAsPSafeArray(Result[1]); 
    Move(Pointer(Data)^, SafeArray.Data^, Length(Data)); 
end; 

Затем на сервере DataSnap, я может извлечь двоичные данные из OleVariant, как это, предполагая, что Value является Result[1] из массива Variant в OleVariant:

procedure GetBinaryData(Value: Variant; Result: TMemoryStream); 
var 
    SafeArray: PVarArray; 
begin 
    SafeArray := VarArrayAsPSafeArray(Value); 
    Assert(SafeArray.ElementSize=1); 
    Result.Clear; 
    Result.WriteBuffer(SafeArray.Data^, SafeArray.Bounds[0].ElementCount); 
end; 
+0

Здесь есть небольшая асимметрия. Первый раздел кода включает 'SizeOf()', а второй - нет. Также не нужно, так как вы знаете, что элементы - это байты размером 1. Но вам, вероятно, следует добавить некоторую проверку здравомыслия ко второму блоку кода, потому что компилятор не может гарантировать содержимое массива вариантов. +1 и спасибо за ваш ранее удаленный комментарий об объяснениях относительно того, почему они ценны. Я стараюсь, и мне приятно, что вы заметили. :-) –

+0

Спасибо @ Давид - Я всегда ценю время, которое вы принимаете, чтобы объяснить ** почему **. Я попытался добавить 'SizeOf()', как вы предлагаете, но не может понять, как получить доступ к элементу 'SafeArray.Data'. Поэтому я добавил 'SizeOf (Byte)' для обоих (чтобы быть последовательным). Хотя это и не идеально ... –

+0

Не возражаете, если я отредактирую ваш ответ, чтобы показать, что я думаю, что вы должны делать?Это будет легче, чем пытаться объяснить это. –

Смежные вопросы