三层中数据流的存储和读取

procedure ParamsToStream(Params: TParams; var Strm: TStream);
var
  I: SmallInt;
  PM: TParam;
  prmName: string;
  nSize: Integer;
  ftp: TFieldType;
  Pnt: Pointer;
begin
  //写入ParamCount
  nSize := Params.Count;
  Strm.Write(nSize, SizeOf(nSize));
  //获取Param
  for I := 0 to Params.Count - 1 do
  begin
    PM := Params[I];
    //写入参数名称
    prmName := PM.Name;
    nSize := Length(prmName);
    Strm.Write(nSize, SizeOf(nSize));
    Strm.Write(prmName[1], nSize);
    //写入数据类型
    ftp := PM.DataType;
    Strm.Write(ftp, SizeOf(ftp));
    //写入数据体
    nSize := PM.GetDataSize;
    Pnt := AllocMem(nSize);
    PM.GetData(Pnt);
    Strm.Write(nSize, SizeOf(nSize));
    Strm.Write(Pnt^, nSize);
    FreeMem(Pnt);
  end;
  Strm.Position := 0;
end;

procedure StreamToParams(Strm: TStream; Params: TParams);
var
  I: SmallInt;
  prmCount, nSize: Integer;
  prmName: string;
  prmType: TFieldType;
  Pnt: Pointer;
  PM: TParam;
begin
  //读取Param总数
  Strm.Position := 0;
  Strm.Read(prmCount, SizeOf(prmcount));
  //读取Param
  for I := 0 to prmCount - 1 do
  begin
    //读取参数名称
    Strm.Read(nSize, SizeOf(nSize));
    SetLength(prmName, nSize);
    Strm.Read(pchar(prmName)^, nSize);
    //读取数据类型
    Strm.Read(prmType, SizeOf(prmType));
    //读取数据体
    Strm.Read(nSize, SizeOf(nSize));
    Pnt := AllocMem(nSize);
    Strm.Read(Pnt^, nSize);

    PM := Params.CreateParam(prmType, prmName, ptInput);

    PM.SetData(Pnt);
    FreeMem(Pnt);
  end;
end;

=========================

unit WebAdoStream;
{****************************************************************
        单元名称:WebAdoStream.pas
        创建日期:2009-10-01
        创建者   本模块改编于 New Midas VCL Library(1.00)的JxStream.pas
        功能:     
        当前版本:
        Email:dcopyboy@tom.com
        QQ:445235526

***************************************************************}
interface

uses Windows, Classes, SysUtils, SqlTimSt, FMTBcd, Variants, db, adodb;

type
  // 存贮版本错误.
  EPersistVersion = class(Exception);
  EPersistError = class(Exception);
  EClassNotFound = class(EPersistError);
  EWriterError = class(EPersistError);
  EReaderError = class(EPersistError);
  // Unicode编码类型.
  TStrTransferFormat = (tfUtf16LE, tfUtf16BE, tfUtf8);
  // 数据写入(以小端格式写入)
  TWAStreamWriter = class
  private
    FStream: TStream;
    FTransferFormat: TStrTransferFormat; // 未用
    procedure Write7BitEncodedInt(value: LongInt);
    // 写入shortstring. 适用于写入ClassName, 因为这些属性以
    // ShortString存在, 如果转换为String再写入, 则多了构造
    // String的步骤, 速度较慢
    procedure WriteShortString(const value: ShortString);
  public
    property Stream: TStream read FStream write FStream;
    property TransferFormat: TStrTransferFormat read FTransferFormat write FTransferFormat;
    procedure WriteBuffer(const Buffer; Count: Longint);
    procedure WriteShortInt(value: ShortInt);
    procedure WriteSmallInt(value: SmallInt);
    procedure WriteLongInt(value: LongInt);
    procedure WriteInt64(value: Int64);
    procedure WriteByte(value: Byte);
    procedure WriteWord(value: Word);
    procedure WriteLongWord(value: LongWord);
    procedure WriteCurrency(value: Currency);
    procedure WriteSingle(value: Single);
    procedure WriteDouble(value: Double);
    procedure WriteBool(value: Boolean);
    procedure WriteDateTime(value: TDateTime);
    procedure WriteAscii(value: string);
    procedure WriteString(value: string);
    procedure WriteOleString(value: WideString);
    procedure WriteBinary(const Buffer; Size: Integer);
    procedure WriteTimeStamp(const ATimeStamp: TSqlTimeStamp);
    procedure WriteFMTBcd(const ABcd: TBcd);
    procedure WriteVariant(const V: Variant);
    procedure WriteObjectProps(Obj: TPersistent);
  end;

  // 数据读取(以小端读取)
  TWAStreamReader = class
  private
    FStream: TStream;
    FTransferFormat: TStrTransferFormat;
    function Read7BitEncodedInt: LongInt;
    function ReadShortString: string;
  public
    property Stream: TStream read FStream write FStream;
    property TransferFormat: TStrTransferFormat read FTransferFormat write FTransferFormat;
    procedure ReadBuffer(var Buffer; Count: Longint);
    function ReadShortInt: ShortInt;
    function ReadSmallInt: SmallInt;
    function ReadLongInt: LongInt;
    function ReadInt64: Int64;
    function ReadByte: Byte;
    function ReadWord: Word;
    function ReadLongWord: LongWord;
    function ReadCurrency: Currency;
    function ReadSingle: Single;
    function ReadDouble: Double;
    function ReadBool: Boolean;
    function ReadDateTime: TDateTime;
    // 读取ASCII字符串, 长度<=255, 多则截断.
    function ReadAscii(len: Byte): string;
    function ReadString: string;
    function ReadOleString: WideString;
    function ReadBinary: string;
    function ReadStream: TStream;
    procedure ReadTimeStamp(var ATimeStamp: TSqlTimeStamp);
    procedure ReadFMTBcd(var ABcd: TBcd);
    function ReadVariant: Variant;
    procedure ReadObjectProps(Obj: TPersistent);
  end;
function AdoQuerySaveTostream(Adoq: Tadoquery): TMemoryStream;
function AdoQueryLoadFromstream(Adoq: Tadoquery; Stream: TMemoryStream): boolean;

implementation
uses TypInfo;

resourcestring
  SInvalidVariantType = '无效的Variant类型 %d';
  SClassNotFound = 'class %s not found.';
  SWriterError = 'Stream write error.';
  SReaderError = 'Stream read error.';
  SPersistClassError = 'Persistable class not supported.';
  SPersistTypeNotSupported = 'Type %s not supported';

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

const
  SimpleArrayTypes = [varSmallInt, varInteger, varSingle, varDouble, varCurrency,
    varDate, varBoolean, varShortInt, varByte, varWord, varLongWord];

  VariantSize: array[0..varLongWord] 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, SizeOf(ShortInt), SizeOf(Byte),
    SizeOf(Word), SizeOf(LongWord));

  CMinVarType = $100;
  StreamFMTBcdID = CMinVarType + 1;
  StreamSQLTimeStampID = CMinVarType + 2;


{ TWAStreamWriter }

procedure TWAStreamWriter.Write7BitEncodedInt(value: Integer);
begin
  while value > $80 do
  begin
    WriteByte(Byte(value or $80));
    value := value shr 7;
  end;
  WriteByte(value and $FF);
end;

procedure TWAStreamWriter.WriteAscii(value: string);
var
  len: Integer;
begin
  len := Length(value);
  if len > 255 then
    len := 255;
  if len > 0 then WriteBuffer(PChar(value)^, len);
end;

procedure TWAStreamWriter.WriteBinary(const Buffer; Size: Integer);
begin
  Write7BitEncodedInt(Size);
  WriteBuffer(Buffer, Size);
end;

procedure TWAStreamWriter.WriteBool(value: Boolean);
begin
  if value then
    WriteByte(1)
  else
    WriteByte(0);
end;

procedure TWAStreamWriter.WriteBuffer(const Buffer; Count: Integer);
begin
  if (Count <> 0) and (Stream.Write(Buffer, Count) <> Count) then
    raise EWriterError.Create(SWriterError);
end;

procedure TWAStreamWriter.WriteByte(value: Byte);
begin
  WriteBuffer(value, 1);
end;

procedure TWAStreamWriter.WriteCurrency(value: Currency);
begin
//  h2n_Data8(value);
  WriteBuffer(value, SizeOf(value));
end;

procedure TWAStreamWriter.WriteDateTime(value: TDateTime);
begin
//  h2n_Data8(value);
  WriteBuffer(value, SizeOf(value));
end;

procedure TWAStreamWriter.WriteDouble(value: Double);
begin
//  h2n_Data8(value);
  WriteBuffer(value, SizeOf(value));
end;

procedure TWAStreamWriter.WriteFMTBcd(const ABcd: TBcd);
begin
  with ABcd do
  begin
    WriteByte(Precision);
    WriteByte(SignSpecialPlaces);
    WriteBuffer(Fraction, SizeOf(Fraction));
  end;
end;

procedure TWAStreamWriter.WriteInt64(value: Int64);
begin
//  h2n_Data8(value);
  WriteBuffer(value, SizeOf(value));
end;

procedure TWAStreamWriter.WriteLongInt(value: Integer);
begin
//  h2n_Data4(value);
  WriteBuffer(value, SizeOf(value));
end;

procedure TWAStreamWriter.WriteLongWord(value: LongWord);
begin
//  h2n_Data4(value);
  WriteBuffer(value, SizeOf(value));
end;

procedure TWAStreamWriter.WriteObjectProps(Obj: TPersistent);
  procedure WriteCollection(Coll: TCollection);
  var
    I: Integer;
  begin
    WriteObjectProps(Coll);
    WriteLongInt(Coll.Count);
    for I := 0 to Coll.Count - 1 do
      WriteObjectProps(Coll.Items[I]);
  end;

var
  TypData: PTypeData;
  PropCount, I, OrdVal: Integer;
  Int64Val: Int64;
  DblVal: Double;
  StrVal: string;
  ObjVal: TObject;
  WVal: WideString;
  VarVal: Variant;
  Props: PPropList;
  PropInfo: PPropInfo;
begin
  TypData := GetTypeData(Obj.ClassInfo);
  if TypData <> nil then
  begin
    PropCount := TypData.PropCount;
    if PropCount > 0 then
    begin
      GetMem(Props, PropCount * SizeOf(PPropInfo));
      try
        PropCount := GetPropList(PTypeInfo(Obj.ClassInfo), tkProperties, Props);

        for I := 0 to PropCount - 1 do
        begin
          PropInfo := Props^[I];
          with PropInfo^ do
          begin
            case PropType^.Kind of
              tkInteger:
                begin
                  OrdVal := GetOrdProp(Obj, PropInfo);
                  WriteLongInt(OrdVal);
//                  case GetTypeData(PropType^).OrdType of
//                    otSByte, otUByte: WriteByte(OrdVal);
//                    otSWord, otUWord: WriteWord(OrdVal);
//                    otSLong, otULong: WriteLongInt(OrdVal);
//                  end;
                end;

              tkInt64:
                begin
                  Int64Val := GetInt64Prop(Obj, PropInfo);
                  WriteInt64(Int64Val);
                end;

              tkEnumeration:
                begin
                  OrdVal := GetOrdProp(Obj, PropInfo);
                  WriteByte(OrdVal);
                end;

              tkFloat:
                begin
                  DblVal := GetFloatProp(Obj, PropInfo);
                  WriteDouble(DblVal);
                end;

              tkLString,
                tkString:
                begin
                  StrVal := GetStrProp(Obj, PropInfo);
                  WriteString(StrVal);
                end;

              tkWString:
                begin
                  WVal := GetWideStrProp(Obj, PropInfo);
                  WriteOleString(WVal);
                end;

              tkClass:
                begin
                  ObjVal := GetObjectProp(Obj, PropInfo);
                  if ObjVal is TStrings then
                    WriteString(TStrings(ObjVal).CommaText)
                  else if ObjVal is TCollection then
                    WriteCollection(TCollection(ObjVal))
                  else if ObjVal is TPersistent then
                    WriteObjectProps(TPersistent(ObjVal))
                  else
                    raise EPersistError.Create(SPersistClassError);
                end;

              tkSet:
                begin
                  OrdVal := GetOrdProp(Obj, PropInfo);
                  WriteLongInt(OrdVal);
                end;

              tkChar:
                begin
                  OrdVal := GetOrdProp(Obj, PropInfo);
                  WriteByte(OrdVal);
                end;

              tkWChar:
                begin
                  OrdVal := GetOrdProp(Obj, PropInfo);
                  WriteSmallInt(OrdVal);
                end;

              tkVariant:
                begin
                  VarVal := TypInfo.GetVariantProp(Obj, PropInfo);
                  WriteVariant(VarVal);
                end;

              tkDynArray:
                begin
                  TypData := GetTypeData(PropInfo.PropType^);
                  assert(TypData <> nil);
                end;
            else
              raise EPersistError.CreateFmt(SPersistTypeNotSupported,
                [GetEnumName(TypeInfo(TTypeKind), Ord(PropInfo.PropType^.Kind))]);
                {
                tkArray,
                tkRecord,
                tkMethod,
                tkInterface,
                tkDynArray
                }
            end; // case
          end; // with
        end; // for
      finally
        FreeMem(Props, PropCount * SizeOf(PPropInfo));
      end;
    end;
  end;
end;

procedure TWAStreamWriter.WriteOleString(value: WideString);
var
  S: string;
  len: Integer;
begin
  S := Utf8Encode(value);
  len := Length(S);
  Write7BitEncodedInt(len);
  if len > 0 then
    WriteBuffer(PChar(S)^, len);
end;

procedure TWAStreamWriter.WriteShortInt(value: ShortInt);
begin
  WriteBuffer(value, SizeOf(value));
end;

procedure TWAStreamWriter.WriteShortString(const value: ShortString);
begin
  WriteByte(Length(value));
  WriteBuffer(value[1], Length(value));
end;

procedure TWAStreamWriter.WriteSingle(value: Single);
begin
//  h2n_Data4(value);
  WriteBuffer(value, SizeOf(value));
end;

procedure TWAStreamWriter.WriteSmallInt(value: SmallInt);
begin
//  value := Word(h2n_Word(Word(value)));
  WriteBuffer(value, SizeOf(value));
end;

procedure TWAStreamWriter.WriteString(value: string);
var
  S: string;
  len: Integer;
begin
  S := AnsiToUtf8(value);
  len := Length(S);
  Write7BitEncodedInt(len);
  if len > 0 then
    WriteBuffer(PChar(S)^, len);
end;

procedure TWAStreamWriter.WriteTimeStamp(const ATimeStamp: TSqlTimeStamp);
begin
  with ATimeStamp do
  begin
    WriteSmallInt(Year);
    WriteWord(Month);
    WriteWord(Day);
    WriteWord(Hour);
    WriteWord(Minute);
    WriteWord(Second);
    WriteLongWord(Fractions);
  end;
end;

procedure TWAStreamWriter.WriteVariant(const V: Variant);

  procedure WriteArray(const V: Variant);
  var
    VType: Word;
    VSize, DimCount, I, ElemSize: Integer;
    LoDim, HiDim: PIntArray;
    Indices: array of Integer;
    P: Pointer;
    V2: Variant;
  begin
    VType := VarType(V) and varTypeMask;
    DimCount := VarArrayDimCount(V);
    VSize := SizeOf(Integer) * DimCount;
    GetMem(LoDim, VSize);
    GetMem(HiDim, VSize);
    try
      for I := 1 to DimCount do
      begin
        LoDim[I - 1] := VarArrayLowBound(V, I);
        HiDim[I - 1] := VarArrayHighBound(V, I);
      end;
      WriteWord(VType or varArray);
      WriteWord(DimCount);
      WriteBuffer(LoDim^, VSize);
      WriteBuffer(HiDim^, VSize);

      if VType in SimpleArrayTypes then
      begin
        ElemSize := VariantSize[VType];
        Assert(ElemSize <> 0);
        VSize := 1;
        for I := 0 to DimCount - 1 do
          VSize := (HiDim[I] - LoDim[I] + 1) * VSize;
        VSize := VSize * ElemSize;
        P := VarArrayLock(V);
        try
          WriteLongInt(VSize);
          WriteBuffer(P^, VSize);
        finally
          VarArrayUnlock(V);
        end;
      end
      else
      begin
        SetLength(Indices, DimCount);

        for I := 0 to DimCount - 1 do
          Indices[I] := LoDim[I];

        while True do
        begin
          V2 := VarArrayGet(V, Indices);
          WriteVariant(V2);
          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;
      end;
    finally
      FreeMem(LoDim);
      FreeMem(HiDim);
    end;
  end;

var
  VType: Word;
  W: WideString;
begin
  VType := VarType(V);
  if (VType and varArray) <> 0 then
    WriteArray(V)
  else
    case VType and varTypeMask of
      varEmpty, varNull:
        begin
          WriteWord(VType);
        end;
      varString:
        begin
          WriteWord(VType and varTypeMask);
          WriteString(V);
        end;
      varOleStr:
        begin
          WriteWord(VType and varTypeMask);
          W := V;
          WriteOleString(W);
        end;
      varVariant:
        begin
          if VType and varByRef <> varByRef then
            raise EWriteError.CreateFmt(SInvalidVariantType, [VType]);
          WriteVariant(Variant(TVarData(V).VPointer^));
        end;
    else begin
        if VarIsFMTBcd(V) then
        begin
          WriteWord(StreamFMTBcdID);
          WriteFMTBcd(VarToBcd(V));
        end
        else if VarIsSQLTimeStamp(V) then
        begin
          WriteWord(StreamSQLTimeStampID);
          WriteTimeStamp(VarToSQLTimeStamp(V));
        end
        else begin
          WriteWord(VType and varTypeMask);
          case VType and varTypeMask of
            varSmallint: WriteSmallInt(V);
            varInteger: WriteLongInt(V);
            varSingle: WriteSingle(V);
            varDouble: WriteDouble(V);
            varCurrency: WriteCurrency(V);
            varDate: WriteDateTime(V);
            varError: WriteLongInt(V);
            varBoolean: WriteBool(V);
            varShortInt: WriteShortInt(V);
            varByte: WriteByte(V);
            varWord: WriteWord(V);
            varLongWord: WriteLongWord(V);
            varInt64: WriteInt64(V);
          else
            raise EWriteError.CreateFmt(SInvalidVariantType, [VType]);
          end;
        end;
      end;
    end;
end;

procedure TWAStreamWriter.WriteWord(value: Word);
begin
//  value := h2n_Word(value);
  WriteBuffer(value, SizeOf(value));
end;

{ TWAStreamReader }

function TWAStreamReader.Read7BitEncodedInt: LongInt;
var
  n: Byte;
  offset: Integer;
begin
  offset := 0;
  Result := 0;
  repeat
    n := ReadByte;
    Result := Result or ((n and $7F) shl offset);
    Inc(offset, 7);
  until (n and $80) = 0;
end;

function TWAStreamReader.ReadAscii(len: Byte): string;
begin
  if len > 0 then
  begin
    SetLength(Result, len);
    ReadBuffer(PChar(Result)^, len);
  end
  else
    Result := '';
end;

function TWAStreamReader.ReadBinary: string;
var
  Len: Integer;
begin
  Len := Read7BitEncodedInt;
  SetLength(Result, Len);
  ReadBuffer(PChar(Result)^, Len);
end;

function TWAStreamReader.ReadStream: Tstream;
var
  Len: Integer;
begin
  Len := Read7BitEncodedInt;
  Result := Tstream.Create;
  ReadBuffer(Result, Len);
end;

function TWAStreamReader.ReadBool: Boolean;
begin
  Result := (ReadByte <> 0);
end;

procedure TWAStreamReader.ReadBuffer(var Buffer; Count: Integer);
begin
  if (Count <> 0) and (Stream.Read(Buffer, Count) <> Count) then
    raise EReaderError.Create(SReaderError);
end;

function TWAStreamReader.ReadByte: Byte;
begin
  ReadBuffer(Result, 1);
end;

function TWAStreamReader.ReadCurrency: Currency;
begin
  ReadBuffer(Result, SizeOf(Currency));
end;

function TWAStreamReader.ReadDateTime: TDateTime;
begin
  ReadBuffer(Result, SizeOf(TDateTime));
end;

function TWAStreamReader.ReadDouble: Double;
begin
  ReadBuffer(Result, SizeOf(Double));
end;

procedure TWAStreamReader.ReadFMTBcd(var ABcd: TBcd);
begin
  with ABcd do
  begin
    Precision := ReadByte;
    SignSpecialPlaces := ReadByte;
    ReadBuffer(Fraction, SizeOf(Fraction));
  end;
end;

function TWAStreamReader.ReadInt64: Int64;
begin
  ReadBuffer(Result, SizeOf(Int64));
end;

function TWAStreamReader.ReadLongInt: LongInt;
begin
  ReadBuffer(Result, SizeOf(LongInt));
end;

function TWAStreamReader.ReadLongWord: LongWord;
begin
  ReadBuffer(Result, SizeOf(LongWord));
end;

procedure TWAStreamReader.ReadObjectProps(Obj: TPersistent);
  procedure ReadCollection(Coll: TCollection);
  var
    I, Len: Integer;
    Item: TCollectionItem;
  begin
    ReadObjectProps(Coll);
    Len := ReadLongInt;
    for I := 0 to Len - 1 do
    begin
      Item := Coll.Add;
      ReadObjectProps(Item);
    end;
  end;
var
  TypData: PTypeData;
  PropCount, I, OrdVal: Integer;
  Props: PPropList;
  Int64Val: Int64;
  DblVal: Double;
  StrVal: string;
  ObjVal: TObject;
  WVal: WideString;
  VarVal: Variant;
  PropInfo: PPropInfo;
begin
  TypData := GetTypeData(Obj.ClassInfo);
  if TypData <> nil then
  begin
    PropCount := TypData.PropCount;
    if PropCount > 0 then
    begin
      GetMem(Props, PropCount * SizeOf(PPropInfo));
      try
        PropCount := GetPropList(PTypeInfo(Obj.ClassInfo), tkProperties, Props);

        for I := 0 to PropCount - 1 do
        begin
          PropInfo := Props^[I];
          with PropInfo^ do
          begin
            case PropType^.Kind of
              tkInteger:
                begin
                  OrdVal := ReadLongInt;
                  SetOrdProp(Obj, PropInfo, OrdVal);
                end;

              tkInt64:
                begin
                  Int64Val := ReadInt64;
                  SetInt64Prop(Obj, PropInfo, Int64Val);
                end;

              tkEnumeration:
                begin
                  OrdVal := ReadByte;
                  SetOrdProp(Obj, PropInfo, OrdVal);
                end;

              tkFloat:
                begin
                  DblVal := ReadDouble;
                  SetFloatProp(Obj, PropInfo, DblVal);
                end;

              tkLString,
                tkString:
                begin
                  StrVal := ReadString;
                  SetStrProp(Obj, PropInfo, StrVal);
                end;

              tkWString:
                begin
                  WVal := ReadOleString;
                  SetWideStrProp(Obj, PropInfo, WVal);
                end;

              tkClass:
                begin
                  ObjVal := GetObjectProp(Obj, PropInfo);
                  if not (ObjVal is TPersistent) then
                    raise EPersistError.Create(SPersistClassError);

                  if ObjVal is TStrings then
                  begin
                    StrVal := ReadString;
                    TStrings(ObjVal).CommaText := StrVal;
                  end
                  else if ObjVal is TCollection then
                    ReadCollection(TCollection(ObjVal))
                  else
                    ReadObjectProps(TPersistent(ObjVal));
                end;

              tkSet:
                begin
                  OrdVal := ReadLongint;
                  SetOrdProp(Obj, PropInfo, OrdVal);
                end;

              tkChar:
                begin
                  OrdVal := ReadByte;
                  SetOrdProp(Obj, PropInfo, OrdVal);
                end;

              tkWChar:
                begin
                  OrdVal := ReadSmallInt;
                  SetOrdProp(Obj, PropInfo, OrdVal);
                end;

              tkVariant:
                begin
                  VarVal := ReadVariant;
                  SetVariantProp(Obj, PropInfo, VarVal);
                end;
            else
              raise EPersistError.CreateFmt(SPersistTypeNotSupported,
                [GetEnumName(TypeInfo(TTypeKind), Ord(PropInfo.PropType^.Kind))]);
            end; // case
          end; // with
        end; // for
      finally
        FreeMem(Props, PropCount * SizeOf(PPropInfo));
      end;
    end;
  end;
end;

function TWAStreamReader.ReadOleString: WideString;
var
  len: Integer;
  s: string;
begin
  len := Read7BitEncodedInt;
  if len > 0 then
  begin
    SetLength(s, len);
    ReadBuffer(PChar(s)^, len);
    Result := Utf8Decode(s);
  end
  else
  begin
    Result := '';
  end;
end;

function TWAStreamReader.ReadShortInt: ShortInt;
begin
  ReadBuffer(Result, SizeOf(ShortInt));
end;

function TWAStreamReader.ReadShortString: string;
var
  Len: Integer;
begin
  Result := '';
  Len := ReadByte;
  if Len = 0 then Exit;
  SetLength(Result, Len);
  ReadBuffer(PChar(Result)^, Len);
end;

function TWAStreamReader.ReadSingle: Single;
begin
  ReadBuffer(Result, SizeOf(Single));
end;

function TWAStreamReader.ReadSmallInt: SmallInt;
begin
  ReadBuffer(Result, SizeOf(SmallInt));
end;

function TWAStreamReader.ReadString: string;
begin
  Result := ReadOleString;
end;

procedure TWAStreamReader.ReadTimeStamp(var ATimeStamp: TSqlTimeStamp);
begin
  with ATimeStamp do
  begin
    Year := ReadSmallInt;
    Month := ReadWord;
    Day := ReadWord;
    Hour := ReadWord;
    Minute := ReadWord;
    Second := ReadWord;
    Fractions := ReadLongWord;
  end;
end;

function TWAStreamReader.ReadVariant: Variant;

  procedure ReadArray(VType: Word; var V: Variant);
  var
    DimCount: Word;
    VSize, I: Integer;
    LoDim, HiDim, Bounds, Indices: array of Integer;
    P: Pointer;
    V2: Variant;
  begin
    VType := VType and varTypeMask;
    DimCount := ReadWord;
    VSize := DimCount * SizeOf(Integer);
    SetLength(LoDim, DimCount);
    SetLength(HiDim, DimCount);
    SetLength(Bounds, DimCount * 2);
    ReadBuffer(LoDim[0], VSize);
    ReadBuffer(HiDim[0], VSize);
    for I := 0 to DimCount - 1 do
    begin
      Bounds[I * 2] := LoDim[I];
      Bounds[I * 2 + 1] := HiDim[I];
    end;
    V := VarArrayCreate(Bounds, VType);

    if VType in SimpleArrayTypes then
    begin
      VSize := ReadLongInt;
      P := VarArrayLock(V);
      try
        ReadBuffer(P^, VSize);
      finally
        VarArrayUnlock(V);
      end;
    end
    else
    begin
      SetLength(Indices, DimCount);
      for I := 0 to DimCount - 1 do
        Indices[I] := LoDim[I];

      while True do
      begin
        V2 := ReadVariant;
        VarArrayPut(V, V2, Indices);
        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;
    end;
  end;

var
  VType: Word;
  ABcd: TBcd;
  ATimeStamp: TSQLTimeStamp;
begin
  VType := ReadWord;
  if VType and varArray <> 0 then
    ReadArray(VType, Result)
  else
    case VType of
      varEmpty: VarClear(Result);
      varNull: Result := Null;
      varString: Result := ReadString;
      varOleStr: Result := ReadOleString;
      varVariant: Result := ReadVariant;
      varSmallint: Result := ReadSmallint;
      varInteger: Result := ReadLongInt;
      varSingle: Result := ReadSingle;
      varDouble: Result := ReadDouble;
      varCurrency: Result := ReadCurrency;
      varDate: Result := ReadDateTime;
      varError:
        begin
          Result := ReadLongInt;
          TVarData(Result).VType := varError;
        end;
      varBoolean: Result := ReadBool;
      varShortInt: Result := ReadShortInt;
      varByte: Result := ReadByte;
      varWord: Result := ReadWord;
      varLongWord: Result := ReadLongWord;
      varInt64: Result := ReadInt64;
    else
      if VType = StreamFMTBcdID then
      begin
        Self.ReadFMTBcd(ABcd);
        Result := VarFMTBcdCreate(ABcd);
      end
      else if VType = StreamSQLTimeStampID then
      begin
        ReadTimeStamp(ATimeStamp);
        Result := VarSQLTimeStampCreate(ATimeStamp);
      end
      else
        raise EReadError.CreateFmt(SInvalidVariantType, [VType]);
    end;
end;

function TWAStreamReader.ReadWord: Word;
begin
  ReadBuffer(Result, SizeOf(Word));
end;

//下列2个过程由Dcopyboy编写
function AdoQuerySaveTostream(Adoq: Tadoquery): TMemoryStream;
var
  aa: TWAStreamWriter;
  i, b: integer;
  Stream: TMemoryStream;
begin
  aa := TWAStreamWriter.Create;
  aa.Stream := TMemoryStream.Create;
  aa.WriteString(Adoq.SQL.Text);
  b := Adoq.Parameters.Count;
  aa.WriteSmallInt(b);
  for i := 0 to b - 1 do begin
    aa.WriteString(adoq.Parameters[i].Name);
    if adoq.Parameters[i].DataType = ftGraphic then begin
      aa.WriteByte(250);
      aa.WriteVariant(adoq.Parameters[i].Value);
    end
    else if adoq.Parameters[i].DataType = ftMemo then begin
      aa.WriteByte(249);
      aa.WriteVariant(adoq.Parameters[i].Value);
    end
    else if adoq.Parameters[i].DataType = ftFmtMemo then begin
      aa.WriteByte(248);
      aa.WriteVariant(adoq.Parameters[i].Value);
    end
    else if adoq.Parameters[i].DataType = ftblob then begin
      aa.WriteByte(247);
      aa.WriteVariant(adoq.Parameters[i].Value);
    end
    else begin
      aa.WriteByte(1);
      aa.WriteVariant(adoq.Parameters[i].Value);
    end;
  end;
  Result := TMemoryStream(aa.Stream);
  aa.Free;
end;

function AdoQueryLoadFromstream(Adoq: Tadoquery; Stream: TMemoryStream): boolean;
var
  aa: TWAStreamReader;
  i, b: integer;
  Stream1: TMemoryStream;
  PName: string;
  Ptype: word;
  MyValue: Variant;
begin
  aa := TWAStreamReader.Create;
  aa.Stream := TMemoryStream.Create;
  Stream.Position := 0;
  TMemoryStream(aa.Stream).LoadFromStream(stream);
  Adoq.Close;
  aa.Stream.Position := 0;
  adoq.SQL.Text := aa.ReadString;
  b := aa.ReadSmallInt;
  for i := 0 to b - 1 do begin
    PName := aa.ReadString;
    Ptype := aa.ReadByte;
    if ptype = 250 then begin
      adoq.Parameters.ParamByName(Pname).DataType := ftGraphic;
      adoq.Parameters.ParamByName(Pname).Value := aa.ReadVariant;
      adoq.Parameters.ParamByName(Pname).DataType := ftGraphic;
    end
    else if ptype = 249 then begin
      adoq.Parameters.ParamByName(Pname).DataType := ftMemo;
      adoq.Parameters.ParamByName(Pname).Value := aa.ReadVariant;
      adoq.Parameters.ParamByName(Pname).DataType := ftMemo;
    end
    else if ptype = 248 then begin
      adoq.Parameters.ParamByName(Pname).DataType := ftFmtMemo;
      adoq.Parameters.ParamByName(Pname).Value := aa.ReadVariant;
      adoq.Parameters.ParamByName(Pname).DataType := ftFmtMemo;
    end
    else if ptype = 247 then begin
      adoq.Parameters.ParamByName(Pname).DataType := ftblob;
      adoq.Parameters.ParamByName(Pname).Value := aa.ReadVariant;
      adoq.Parameters.ParamByName(Pname).DataType := ftblob;
    end
    else begin
      adoq.Parameters.ParamByName(Pname).Value := aa.ReadVariant;
    end;
  end;
  aa.Free;
  Result := true;
end;

end.

 

 

===============窗体调用调用=================

 

 

 

 

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, WebAdoStream, DB, ADODB, ExtCtrls, ComCtrls, jpeg;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ADOConnection1: TADOConnection;
    ADOQuery1: TADOQuery;
    RichEdit1: TRichEdit;
    Image1: TImage;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{
//测试用表:
CREATE TABLE [dbo].[test] (
 [f1] [float] NULL ,
 [f2] [int] NULL ,
 [f3] [money] NULL ,
 [f4] [numeric](18, 0) NULL ,
 [f5] [real] NULL ,
 [d1] [datetime] NULL ,
 [c1] [char] (10) NULL ,
 [c2] [varchar] (50) NULL ,
 [b1] [ntext] NULL ,
 [b2] [text] NULL ,
 [b3] [image] NULL ,
 [B4] [image] NULL ,
 [id] [int] IDENTITY (1, 1) NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
}

procedure TForm1.Button1Click(Sender: TObject);
var
  Stream1: TMemoryStream;
begin
  ADOQuery1.Close;
  ADOQuery1.SQL.Text := 'Insert into test ( f1,f2,f3,f4,f5,d1,c1,c2,b1,b2,b3,b4) ' +
    ' values ( :f1,:f2,:f3,:f4,:f5,:d1,:c1,:c2,:b1,:b2,:b3,:b4) ';
  ADOQuery1.Parameters.ParamByName('f1').Value := 10;
  ADOQuery1.Parameters.ParamByName('f2').Value := 20;
  ADOQuery1.Parameters.ParamByName('f3').Value := 30;
  ADOQuery1.Parameters.ParamByName('f4').Value := 40;
  ADOQuery1.Parameters.ParamByName('f5').Value := 50;
  ADOQuery1.Parameters.ParamByName('d1').Value := now();
  ADOQuery1.Parameters.ParamByName('c1').Value := '字段1';
  ADOQuery1.Parameters.ParamByName('c2').Value := '字段2';
  ADOQuery1.Parameters.ParamByName('b1').LoadFromFile('本草纲目.txt', ftMemo);
  ADOQuery1.Parameters.ParamByName('b2').LoadFromFile('本草纲目.txt', ftMemo);
  ADOQuery1.Parameters.ParamByName('b3').LoadFromFile('东阳.jpg', ftblob);
  ADOQuery1.Parameters.ParamByName('b4').LoadFromFile('东阳.jpg', ftGraphic);
  Stream1 := TMemoryStream.Create;
  Stream1.LoadFromStream(AdoQuerySaveTostream(ADOQuery1));
  stream1.SaveToFile('c:/parastreamtest');
  Stream1.Free;
  Stream1 := TMemoryStream.Create;
  stream1.LoadFromFile('c:/parastreamtest');
  ADOQuery1.Close;
  ADOQuery1.sql.clear;
  AdoQueryLoadFromstream(ADOQuery1, Stream1);
  ADOQuery1.ExecSQL;
  Stream1.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Stream1: TMemoryStream;
begin
  RichEdit1.Lines.Clear;
  ADOQuery1.Close;
  ADOQuery1.SQL.Text := 'select b1 from test ';
  ADOQuery1.open;
  Stream1 := TMemoryStream.Create;
  Tmemofield(ADOQuery1.FieldByName('b1')).SaveToStream(stream1);
  stream1.Position := 0;
  RichEdit1.Lines.LoadFromStream(stream1);
  stream1.free;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  Stream1: TMemoryStream;
begin
  RichEdit1.Lines.Clear;
  ADOQuery1.Close;
  ADOQuery1.SQL.Text := 'select b2 from test ';
  ADOQuery1.open;
  Stream1 := TMemoryStream.Create;
  Tmemofield(ADOQuery1.FieldByName('b2')).SaveToStream(stream1);
  stream1.Position := 0;
  RichEdit1.Lines.LoadFromStream(stream1);
  stream1.free;

end;

procedure TForm1.Button4Click(Sender: TObject);
var
  Stream1: TMemoryStream;
  Jpeg1: TJPEGImage;
begin
  ADOQuery1.Close;
  ADOQuery1.SQL.Text := 'select b3 from test ';
  ADOQuery1.open;
  Stream1 := TMemoryStream.Create;
  Tblobfield(ADOQuery1.FieldByName('b3')).SaveToStream(stream1);
  stream1.Position := 0;
  Jpeg1 := TJPEGImage.Create;
  Jpeg1.LoadFromStream(stream1);
  stream1.free;
  Image1.Picture.Assign(jpeg1);
  jpeg1.Free;
end;

procedure TForm1.Button5Click(Sender: TObject);
var
  Stream1: TMemoryStream;
  Jpeg1: TJPEGImage;
begin
  ADOQuery1.Close;
  ADOQuery1.SQL.Text := 'select b4 from test ';
  ADOQuery1.open;
  Stream1 := TMemoryStream.Create;
  Tblobfield(ADOQuery1.FieldByName('b4')).SaveToStream(stream1);
  stream1.Position := 0;
  Jpeg1 := TJPEGImage.Create;
  Jpeg1.LoadFromStream(stream1);
  stream1.free;
  Image1.Picture.Assign(jpeg1);
  jpeg1.Free;

end;

end.

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值