怎样返回Variant变量的长度和保存到文件中间?(10分)

  • 主题发起人 主题发起人 biggo
  • 开始时间 开始时间
B

biggo

Unregistered / Unconfirmed
GUEST, unregistred user!
我想把Variant变量中间的内容保存到文件中间。变量的值可能是文本,也可能是二进制数据流。
怎样保存到文件,还有,返回Variant变量的数据长度怎么返回?
先说明用语句:VarArrayHighBound (v, 1) - VarArrayLowBound(v, 1) + 1返回长度是无效的,
它是返回Variant数组的长度不是整个Variant变量的实际长度
如果一个Variant变量没有被VarArrayCreate语句初始化,那么上面这条语句将产生执行异常。
 
fillchar(Variant,sizeof(Variant),0);
 
sizeof(Variant)好象不行,它返回16
并不是我里面内容的长度
 
要看你的Variant里存储的是什么内容,如果是简单类型sizeof就可以,
像结构,文件之类的Variant结构中有一项是指向这些内容的指针。所以取sizeof
只是得到指针变量的size,而不是内容的size。
你可以用Stream来转换。
先都文件到FileStream,由StreamToVariant。
反过来就VariantToStream,在由FileStream写道文件中。
很好用的。
procedure VariantToStream(const Data: OleVariant; Stream: TStream);
var
p: Pointer;
begin
p := VarArrayLock(Data);
try
Stream.Write(p^, VarArrayHighBound(Data,1) + 1); //assuming low bound = 0
finally
VarArrayUnlock(Data);
end;
end;

function StreamToVariant(Stream: TStream): OleVariant;
var
p: Pointer;
begin
Result := VarArrayCreate([0, Stream.Size - 1], varByte);
p := VarArrayLock(Result);
try
Stream.Position := 0; //start from beginning of stream
Stream.Read(p^, Stream.Size);
finally
VarArrayUnlock(Result);
end;
end;
 
答[red]GanQuan[/red]
很不幸,你采用的方法,在我的问题中已经说明过了
VarArrayHighBound(Data,1)语句不能正常执行。
StreamToVariant函数能执行。
VariantToStream函数不能执行。
因为,VariantToStream的变量const Data: OleVariant
如果不是经过VarArrayCreate初始化过的话,执行到 p := VarArrayLock(Data);就在执行的时候报错了。
 
不会吧,我一直都是这样传文件的。
这两个函数必须配套使用,因为函数中Variant的格式是固定的。
你有没有按我说的过程写个程序试一试?
 
给你写一段试试,文件可以任意,不要告诉我不能执行哦 :-)
var
Form1: TForm1;
V: OleVariant;
implementation

{$R *.dfm}
procedure VariantToStream(const Data: OleVariant; Stream: TStream);
var
p: Pointer;
begin
p := VarArrayLock(Data);
try
Stream.Write(p^, VarArrayHighBound(Data,1) + 1); //assuming low bound = 0
finally
VarArrayUnlock(Data);
end;
end;

function StreamToVariant(Stream: TStream): OleVariant;
var
p: Pointer;
begin
Result := VarArrayCreate([0, Stream.Size - 1], varByte);
p := VarArrayLock(Result);
try
Stream.Position := 0; //start from beginning of stream
Stream.Read(p^, Stream.Size);
finally
VarArrayUnlock(Result);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
Mystream: TFileStream;
begin
MyStream := TFileStream.Create('e:/aaa.txt',fmOpenRead);
MyStream.Position := 0;
V := StreamToVariant(MyStream);
MyStream.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
Mystream: TFileSTream;
begin
MyStream := TFileSTream.Create('e:/bbb.txt',fmCreate);
VariantToStream(V,MyStream);
MysTream.Free;
end;
 
答[red]GanQuan[/red][:)][:D][8D][:(][:(!][^][?]
真的不性,确实用不了,不是你的程序用不了,而是你的方法按照我的要求不能成功

你的代码中间的操作,必须是成对出现的。先StreametoVariant然后VarianttoStreame
这样操作就不会有问题,
如果我的变量V不是通过StreametoVariant产生的,例如
把butte1的代码改成
直接付值v:='12345678',那么,你再执行Butte2你就会发现问题所在了。

而我实际使用中间,V的值不一定是由streamtoVariant产生的啊!
 
对,是必须成对使用。
我的意思是最好成对使用。这样可以把所有的类型都统一起来使用同一种方法。
例如
v:='12345678'
也通过Stream,再到Variant。
如var Mystream: TMemoryStream;
Mystream := TMemorysTream.Create;
MyStream.Write(buf,Length(buf));
v: = StreamToVariant(MyStream);
MyStream.Free;
然后可以反过来解出来。任何类型都这样解决达到统一。
 
你这样效率太低了,如果我的数据量大的话,1M,10M甚至更多的M,好象这种方法不可行吧。
好人做到底,想一个办法,用最高的效率完成我要做的事情。
任意内容的Variant数据,直接写到文件中间去。
实际上就是想办法,返回Variant数据地址和数据的长度这两件事,
看资料,好象都只说了,Variant只有为varArray类型返回数据地址,和长度的函数,
没有返回其他类型的数据地址和长度的方法!
谁能想办法解决!!
 
这个问题很久也没有人解决吗?呵呵
我今天也遇到了这个问题.我是这样做的.
你自己保存一下 stream的长度. Variant 存储后就可以了啊!.

 
发现不是这么简单的. 因为存储后再读进来就不对了,变量没有赋值....??? 这是为什么呀?

 
后退
顶部