Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 将[array of byte]分配给没有Unicode转换的变量_Delphi_Type Conversion_Delphi Xe2_Variant_Ansistring - Fatal编程技术网

Delphi 将[array of byte]分配给没有Unicode转换的变量

Delphi 将[array of byte]分配给没有Unicode转换的变量,delphi,type-conversion,delphi-xe2,variant,ansistring,Delphi,Type Conversion,Delphi Xe2,Variant,Ansistring,考虑以下代码段(在Delphi XE2中): Base64Val是编码为Base64的二进制值(因此没有null字节)。(OleVariant)结果将在客户端应用程序和DataSnap服务器之间自动编组和发送 当我用Wireshark捕获流量时,我看到StrVal和Base64Val都作为Unicode字符串传输。如果可以,我希望避免对Base64Val进行Unicode转换。我查看了所有的Variant类型,除了varString之外,没有任何其他类型可以传输字符数组 我发现它显示了如何创建一

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

Base64Val
是编码为Base64的二进制值(因此没有
null
字节)。(
OleVariant
结果将在客户端应用程序和DataSnap服务器之间自动编组和发送

当我用Wireshark捕获流量时,我看到
StrVal
Base64Val
都作为Unicode字符串传输。如果可以,我希望避免对
Base64Val
进行Unicode转换。我查看了所有的
Variant
类型,除了
varString
之外,没有任何其他类型可以传输字符数组


我发现它显示了如何创建一个变量字节数组。我想我可以使用这种技术,而不是使用
ansisting
。不过我很好奇,有没有另一种方法可以在不转换为Unicode字符串的情况下将非Unicode字符数据数组分配给变量?

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

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


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

与问题中的示例保持一致,这就是我如何使其工作的(使用问题中引用的另一个问题的代码和注释):

然后在DataSnap服务器上,我可以像这样从OleVariant中提取二进制数据,假设OleVariant中的变量数组中的
Value
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;

“这些代码是varString和varUString。”-AFAIR,表示短字符串。对于AnsiString,有varLString//PS:如果二进制流由于任何原因不可行,而base64也不可行,那么还有yEnc编码heavy@Arioch不,那些是长串的,让它工作吧。它通过PVarray发送二进制数据,在OleVariant中进行编组,而不使用Base64。我将分别发布答案,包括大卫的另一个答案,在那里他展示了如何做大部分工作。这里有一点不对称。代码的第一部分包括
SizeOf()
,但第二部分没有。这两者都不是必需的,因为您知道元素是大小为1的字节。但是您可能应该在第二个代码块中添加一些健全性检查,因为编译器无法保证变量数组的内容+1并且感谢您先前已删除的关于为什么有价值的解释的评论。我确实试过了,我很高兴你注意到了。:-)谢谢@David-我一直很感谢你花时间解释原因。我尝试按照您的建议添加
SizeOf()
,但不知道如何访问
SafeArray.Data
的元素。所以我在两者中添加了
SizeOf(Byte)
(为了保持一致)。虽然,这也不是完美的…你介意我编辑你的答案来显示我认为你应该做什么吗?这比试图解释要容易得多。你的问题是关于解释器的,你的答案是关于解释器的。也许我错过了什么…@Arioch'The实际上只是一个字节数组编组问题
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;
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;