将[byte of byte]分配给没有Unicode转换的Variant

时间:2013-11-22 06:53:41

标签: delphi type-conversion delphi-xe2 variant ansistring

考虑以下代码片段(在Delphi XE2中):

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捕获流量时,我发现StrValBase64Val都作为Unicode字符串传输。如果可以,我想避免Base64Val的Unicode转换。我查看了所有Variant类型,除了varString之外没有其他任何可以传输字符数组的内容。

我发现this question显示了如何创建变量字节数组。我想我可以使用这种技术而不是使用AnsiString。我很好奇,是否有另一种方法可以将一个非Unicode字符数据数组分配给Variant而不转换为Unicode字符串?

2 个答案:

答案 0 :(得分:4)

Delphi的实现支持使用自定义变体类型代码在Ansiant中存储AnsiString和UnicodeString。这些代码是varString和varUString。

但是interop通常使用标准的OLE变体,而OLE字符串varOleStr是16位编码的。这似乎是你观察的原因。

如果您希望避免转换为16位文本,则需要将数据作为字节数组输入。这样做会使base64编码变得毫无意义。停止base64编码有效负载并以字节数组发送二进制文件。

答案 1 :(得分: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来自OleVariant中Variant数组的Result[1]

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;