晕头了:Byte数组与OleVariant类型互转问题

haj77 2008-02-22 05:16:47
这几天被这个问题搞晕了:Byte数组转换成OleVariant类型后,为什么无法再转换回来呢?

function ByteToOleVariant(Strm: Array of byte ): OleVariant;
var
Data: PByteArray;
i :integer;
begin
Result := VarArrayCreate([0, high(Strm)-Low(Strm)], varByte);
Data := VarArrayLock(Result);
try
for i:=Low(Strm) to high(Strm) do
Data^[i]:=Strm[i] ;
finally
VarArrayUnlock(Result);
end;
end;


Procedure VariantToByte(const Data: OleVariant);
var
p: Pointer;
Stream :TMemoryStream;
MyByte: Array of Byte;
begin
Stream:=TMemoryStream.Create;
p := VarArrayLock(Data);
try
Stream.Write(p^, VarArrayHighBound(Data,1) + 1);
finally
VarArrayUnlock(Data);
end;

SetLength(MyByte,Stream.Size);
Stream.read(MyByte[0],Stream.Size);
//查看MyByte数组发现全为0
end;


procedure TForm1.Button2Click(Sender: TObject);
var
ams,gms : TMemoryStream;
FilePath :String;
MS : OleVariant;
Buf1,Buf2 :Array of byte;
begin
FilePath:='E:\M0120.JPG';
ams :=TMemoryStream.Create;
ams.LoadFromFile(FilePath);
setLength(Buf1,ams.Size);
ams.read(Buf1[0],ams.Size); //一次性将文件的内容读入BUF1这个数组

MS:=ByteToOleVariant(Buf1); //将Byte数组转换为OleVariant;
VariantToByte(MS); //将OleVariant转换为Byte数组;
...全文
963 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
yemkuhan 2011-05-06
  • 打赏
  • 举报
回复
收藏一个
mingyue99 2010-08-02
  • 打赏
  • 举报
回复
收藏了
zhaigates 2009-09-20
  • 打赏
  • 举报
回复
学习啦,谢谢
僵哥 2009-05-13
  • 打赏
  • 举报
回复
我挖
haj77 2008-02-24
  • 打赏
  • 举报
回复
procedure TForm1.Button1Click(Sender: TObject);
var
ams,gms : TMemoryStream;
FilePath :String;
Myvariant : OleVariant;
begin
ams :=TMemoryStream.Create;
gms :=TMemoryStream.Create;
FilePath:='c:\Tmp.jpg';
ams.LoadFromFile(FilePath);

Myvariant:=ReadArray(varByte,ams); //执行到函数时报错: Error Creating Variant or Saft array ???
WriteArray(Myvariant,gms);

gms.SaveToFile('c:\tmp1.jpg');
end;
haj77 2008-02-24
  • 打赏
  • 举报
回复
请问函数如何使用?

function GetVariantPointer(const Value: OleVariant): Pointer;
function ReadArray(VType: Integer;const Data: TStream): OleVariant;
procedure WriteArray(const Value: OleVariant; const Data: TStream);
function ReadVariant(out Flags: TVarFlags;const Data: TStream): OleVariant;
procedure WriteVariant(const Value: OleVariant;const Data: TStream);
僵哥 2008-02-24
  • 打赏
  • 举报
回复
uses activex;
function Stream2OleVariantBytes(const Stream:TStream):OleVariant;
var
Data:Pointer;
begin
Result := VarArrayCreate([0,Stream.Size-1],varByte);
Data := VarArrayLock(Result);
try
Stream.Position := 0;
Stream.Read(Data^,Stream.Size);
finally
VarArrayUnlock(Result);
end;
end;

procedure OleVariantBytes2Stream(const VValue:OleVariant; Stream:TStream);
var
Data:Pointer;
V:OleVariant;
begin
Data := VarArrayLock(VValue);
try
Stream.Seek(0,soFromEnd);
Stream.Write(Data^,(VarArrayHighBound(VValue,1)-VarArrayLowBound(VValue,1)+1) * SafeArrayGetElemSize(PSafeArray(TVarData(VValue).VPointer)))
finally
VarArrayUnlock(VValue);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
V:OleVariant;
m:TMemoryStream;
begin
m:= TMemoryStream.Create;
try
Memo1.Lines.SaveToStream(m);
V:=Stream2OleVariantBytes(m);
m.Clear;
Memo2.Lines.SaveToStream(m);
OleVariantBytes2Stream(V,M);
m.Position := 0;
Caption := IntToStr(m.Size);
Memo2.Lines.LoadFromStream(m);
finally
m.Free;
end;
end;
gjw310 2008-02-23
  • 打赏
  • 举报
回复
僵哥以前写的例子吧,代码收了
僵哥 2008-02-22
  • 打赏
  • 举报
回复
function ReadVariant(out Flags: TVarFlags;
const Data: TStream): OleVariant;
var
I, VType: Integer;
W: WideString;
TmpFlags: TVarFlags;
begin
VarClear(Result);
Flags := [];
Data.Read(VType, SizeOf(VType));
if VType and varByRef = varByRef then Include(Flags, vfByRef);
if VType = varByRef then
begin
Include(Flags, vfVariant);
Result := ReadVariant(TmpFlags, Data);
Exit;
end;
if vfByRef in Flags then VType := VType xor varByRef;
if (VType and varArray) = varArray then
Result := ReadArray(VType, Data) else
case VType and varTypeMask of
varEmpty: VarClear(Result);
varNull: Result := NULL;
varOleStr:
begin
Data.Read(I, SizeOf(Integer));
SetLength(W, I);
Data.Read(W[1], I * 2);
Result := W;
end;
{varDispatch:
begin
Data.Read(I, SizeOf(Integer));
Result := TDataDispatch.Create(Self, I) as IDispatch;
end;}
//varUnknown:
// raise EInterpreterError.CreateResFmt(@SBadVariantType,[IntToHex(VType,4)]);
else
TVarData(Result).VType := VType;
Data.Read(TVarData(Result).VPointer, VariantSize[VType and varTypeMask]);
end;
end;
procedure WriteVariant(const Value: OleVariant;
const Data: TStream);
var
I, VType: Integer;
W: WideString;
begin
VType := VarType(Value);
if VarIsArray(Value) then
WriteArray(Value, Data) else
case (VType and varTypeMask) of
varEmpty, varNull: Data.Write(VType, SizeOf(Integer));
varOleStr:
begin
W := WideString(Value);
I := Length(W);
Data.Write(VType, SizeOf(Integer));
Data.Write(I,SizeOf(Integer));
Data.Write(W[1], I * 2);
end;
{varDispatch:
begin
//if VType and varByRef = varByRef then
// raise EInterpreterError.CreateResFmt(@SBadVariantType,[IntToHex(VType,4)]);
I := StoreObject(Value);
Data.Write(VType, SizeOf(Integer));
Data.Write(I, SizeOf(Integer));
end;}
varVariant:
begin
//if VType and varByRef <> varByRef then
// raise EInterpreterError.CreateResFmt(@SBadVariantType,[IntToHex(VType,4)]);
I := varByRef;
Data.Write(I, SizeOf(Integer));
WriteVariant(Variant(TVarData(Value).VPointer^), Data);
end;
//varUnknown:
// raise EInterpreterError.CreateResFmt(@SBadVariantType,[IntToHex(VType,4)]);
else
Data.Write(VType, SizeOf(Integer));
if VType and varByRef = varByRef then
Data.Write(TVarData(Value).VPointer^, VariantSize[VType and varTypeMask]) else
Data.Write(TVarData(Value).VPointer, VariantSize[VType and varTypeMask]);
end;
end;
end.
僵哥 2008-02-22
  • 打赏
  • 举报
回复
unit VBVariants;

interface
uses
Variants,Classes,ActiveX,ComObj;
const

EasyArrayTypes = [varSmallInt, varInteger, varSingle, varDouble, varCurrency,
varDate, varBoolean, varByte];

VariantSize: array[0..varByte] of Word = (0, 0, SizeOf(SmallInt), SizeOf(Integer),
SizeOf(Single), SizeOf(Double), SizeOf(Currency), SizeOf(TDateTime), 0, 0,
SizeOf(Integer), SizeOf(WordBool), 0, 0, 0, 0, 0, SizeOf(Byte));

type

PIntArray = ^TIntArray;
TIntArray = array[0..0] of Integer;

PVariantArray = ^TVariantArray;
TVariantArray = array[0..0] of OleVariant;

TVarFlag = (vfByRef, vfVariant);
TVarFlags = set of TVarFlag;
function GetVariantPointer(const Value: OleVariant): Pointer;
function ReadArray(VType: Integer;const Data: TStream): OleVariant;
procedure WriteArray(const Value: OleVariant; const Data: TStream);
function ReadVariant(out Flags: TVarFlags;const Data: TStream): OleVariant;
procedure WriteVariant(const Value: OleVariant;const Data: TStream);
implementation

function GetVariantPointer(const Value: OleVariant): Pointer;
begin
case VarType(Value) of
varEmpty, varNull: Result := nil;
varDispatch: Result := TVarData(Value).VDispatch;
varVariant: Result := @Value;
varUnknown: Result := TVarData(Value).VUnknown;
else
Result := @TVarData(Value).VPointer;
end;
end;

function ReadArray(VType: Integer;
const Data: TStream): OleVariant;
var
Flags: TVarFlags;
LoDim, HiDim, Indices, Bounds: PIntArray;
DimCount, VSize, i: Integer;
{P: Pointer;}
V: OleVariant;
LSafeArray: PSafeArray;
P: Pointer;
begin
VarClear(Result);
Data.Read(DimCount, SizeOf(DimCount));
VSize := DimCount * SizeOf(Integer);
GetMem(LoDim, VSize);
try
GetMem(HiDim, VSize);
try
Data.Read(LoDim^, VSize);
Data.Read(HiDim^, VSize);
GetMem(Bounds, VSize * 2);
try
for i := 0 to DimCount - 1 do
begin
Bounds[i * 2] := LoDim[i];
Bounds[i * 2 + 1] := HiDim[i];
end;
Result := VarArrayCreate(Slice(Bounds^,DimCount * 2), VType and varTypeMask);
finally
FreeMem(Bounds);
end;
if VType and varTypeMask in EasyArrayTypes then
begin
Data.Read(VSize, SizeOf(VSize));
P := VarArrayLock(Result);
try
Data.Read(P^, VSize);
finally
VarArrayUnlock(Result);
end;
end else
begin
LSafeArray := PSafeArray(TVarData(Result).VArray);
GetMem(Indices, VSize);
try
FillChar(Indices^, VSize, 0);
for I := 0 to DimCount - 1 do
Indices[I] := LoDim[I];
while True do
begin
V := ReadVariant(Flags, Data);
if VType and varTypeMask = varVariant then
OleCheck(SafeArrayPutElement(LSafeArray, Indices^, V)) else
OleCheck(SafeArrayPutElement(LSafeArray, Indices^, TVarData(V).VPointer^));
Inc(Indices[DimCount - 1]);
if Indices[DimCount - 1] > HiDim[DimCount - 1] then
for i := DimCount - 1 downto 0 do
if Indices[i] > HiDim[i] then
begin
if i = 0 then Exit;
Inc(Indices[i - 1]);
Indices[i] := LoDim[i];
end;
end;
finally
FreeMem(Indices);
end;
end;
finally
FreeMem(HiDim);
end;
finally
FreeMem(LoDim);
end;
end;

procedure WriteArray(const Value: OleVariant;
const Data: TStream);
var
VType, VSize, i, DimCount, ElemSize: Integer;
LSafeArray: PSafeArray;
LoDim, HiDim, Indices: PIntArray;
V: OleVariant;
P: Pointer;
begin
VType := VarType(Value);
LSafeArray := PSafeArray(TVarData(Value).VPointer);
Data.Write(VType, SizeOf(Integer));
DimCount := VarArrayDimCount(Value);
Data.Write(DimCount, SizeOf(DimCount));
VSize := SizeOf(Integer) * DimCount;
GetMem(LoDim, VSize);
try
GetMem(HiDim, VSize);
try
for i := 1 to DimCount do
begin
LoDim[i - 1] := VarArrayLowBound(Value, i);
HiDim[i - 1] := VarArrayHighBound(Value, i);
end;
Data.Write(LoDim^,VSize);
Data.Write(HiDim^,VSize);
if VType and varTypeMask in EasyArrayTypes then
begin
ElemSize := SafeArrayGetElemSize(LSafeArray);
VSize := 1;
for i := 0 to DimCount - 1 do
VSize := (HiDim[i] - LoDim[i] + 1) * VSize;
VSize := VSize * ElemSize;
P := VarArrayLock(Value);
try
Data.Write(VSize, SizeOf(VSize));
Data.Write(P^,VSize);
finally
VarArrayUnlock(Value);
end;
end else
begin
GetMem(Indices, VSize);
try
for I := 0 to DimCount - 1 do
Indices[I] := LoDim[I];
while True do
begin
if VType and varTypeMask <> varVariant then
begin
OleCheck(SafeArrayGetElement(LSafeArray, Indices^, TVarData(V).VPointer));
TVarData(V).VType := VType and varTypeMask;
end else
OleCheck(SafeArrayGetElement(LSafeArray, Indices^, V));
WriteVariant(V, Data);
Inc(Indices[DimCount - 1]);
if Indices[DimCount - 1] > HiDim[DimCount - 1] then
for i := DimCount - 1 downto 0 do
if Indices[i] > HiDim[i] then
begin
if i = 0 then Exit;
Inc(Indices[i - 1]);
Indices[i] := LoDim[i];
end;
end;
finally
FreeMem(Indices);
end;
end;
finally
FreeMem(HiDim);
end;
finally
FreeMem(LoDim);
end;
end;

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧