3

考虑以下代码片段(在 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. 我查看了所有类型,除了可以传输字符数组Variant之外没有其他任何东西。varString

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

4

2 回答 2

4

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

但是互操作通常会使用标准的 OLE 变体,并且 OLE 字符串 varOleStr 是 16 位编码的。这似乎是你观察的原因。

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

于 2013-11-22T07:28:48.233 回答
2

与问题中的示例保持一致,这就是我使其工作的方式(使用大卫对我的问题中引用的另一个问题的回答中的代码和评论):

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 中提取二进制数据,假设来自 OleVariantValueResult[1]的 Variant Array:

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;
于 2013-11-22T09:22:13.867 回答