Reading VARIANT from Stream - Delphi’s Way
In this post I described an efficient way to write a VARIANT to a stream in a binary format. Doing so will be of no use whatsoever if you cannot bring back a fully-fledged VARIANT from the stream.
Reading a VARIANT is analoguous to writing it, but there is an interesting points. You have to know how to set properly the type of the output variant. If the VARIANT is a single value, the right way to do it is to use VarCast function. If the VARIANT is an array, however, you should create it by using VarArrayCreate. Only after you set the type, you can assign the data.
Here comes the code:
August 3rd, 2008 at 3:08 am
Very nice!!
August 13th, 2008 at 4:18 am
[…] tarde encontrei os posts de Nikolay Pavlov - nem acredito que encontrei um parente de Pavlov e ainda um que programa em Delphi! Nikolay estava […]
August 17th, 2008 at 7:05 am
Your blog is interesting!
Keep up the good work!
October 26th, 2008 at 6:53 pm
Thanx, for the sample, Nic. Which unit did you use for IsSimpleType() and GetSimpleTypeSize(0) ?
October 27th, 2008 at 11:58 am
Hans,
These two functions are mine as well, but I forgot to provide the code for them. They don’t do anything much special, I use them as kind of C macros.
Here they are.
function IsSimpleType (VarType: word) : boolean;
begin
Result := (VarType and varTypeMask) in
[varByte, varSmallint, varInteger, varSingle, varDouble, varCurrency, varDate, varError, varBoolean];
end;
function GetSimpleTypeSize (VarType: word): integer;
begin
case VarType and varTypeMask of
varSmallint: Result := SizeOf (Smallint);
varInteger: Result := SizeOf (Integer);
varSingle: Result := SizeOf (Single);
varDouble: Result := SizeOf (Double);
varCurrency: Result := SizeOf (Currency);
varDate: Result := SizeOf (Double);
varError: Result := SizeOf (Longint);
varBoolean: Result := SizeOf (Boolean);
varByte: Result := SizeOf (Byte);
else
Result := -1;
end;
end;
March 24th, 2009 at 3:08 pm
the line
Stream.Seek (0, soFromBeginning);
is problematic. What if someone writes several variants into the same stream?
It should be up to the user to set the correct position in the stream.
May 27th, 2009 at 2:19 pm
Tim, I agree. Thanks for pointing this out.
However, my goal was to show how to (de)serialize variants, and such details like position in the stream can be handled by developers themselves. That’s why I won’t edit the code in the post.
October 26th, 2009 at 2:56 pm
Very nice code! Thanks for the great work.
However, when I try to deserialize a TFileStream, Delphi raises the exception EVariantTypeCastError: \’Could not convert variant of type (Empty) into type ($0996)\’. The file stream contains a TClientDataSet (that has been saved to a file).
How can I solve the problem?
November 2nd, 2009 at 12:25 pm
Christian, I believe you misunderstood the purpose of the code. The sample above deserializes a variant, serialized by the the appropriate code of another post (see the link in the first sentence).
November 13th, 2009 at 12:33 am
Nik, I’m sorry, I think I’ve got some things wrong in my original question. However, I am using your code (this post and the other one) to transmit stream data via variants. Now I want to do the following: I have a TClientDataset that has been created and saved to a file (by another application). In my code, on the server side, I read this TClientDataset into a file stream. When trying to convert this file stream to a variant to send it to the Client, I get the mentioned EVariantTypeCastError.
July 14th, 2010 at 1:44 pm
I propose not to wait until you get enough money to buy goods! You should just take the credit loans or just collateral loan and feel fine