Delphi向Ini文件中写入流数据

Delphi中使用Ini文件是非常方便的,很简单的就可以操作一个Ini文件。但是也存在着局限性,比如TIniFile的ReadString函数最大只能读2047个字符,超过了的则读不出来,鉴于这个,很容易的修改,可以找到其ReadString函数,扩大其缓冲区则可。同时还有一点不足之处就是,不能写入流。写入流有的时候,用处也是非常大的了。但是Ini文件却没有提供该函数,进日由于工作中需要用到这样的东西,于是想了一个办法能够在Ini文件中读写流数据。其实写入流数据也是输入字符串。Ini文件中输入的字符串不能换行,否则换行后的字符串则成一个非有效的值了。所以,把流数据当字符串输入的时候,就要防止其有换行符号,于是想到一个办法,先把他变成16进制字符串,然后在写入这样就防止了换行。读出来,也就把16进制字符串再转换成二进制数据。
所以就需要如下几个函数了:
Function StreamToStr(Value: TStream): String; //流转化成16进制字符串
Function StrToStream(Const aStr: String; Value: TStream): Integer;//16进制字符串化为流数据
Function ReadStream(Const Section,aParamName: String; aValue: TStream): Integer;//读取流
Procedure WriteStream(Const Section,aParamName: String; aValue: TStream);//写入流
//*************************************************************
//    功能:指针区信息转16进制
//    参数: Ptr指定指针,Len指定取得的数据长度
//*************************************************************
function PointToHex(Const Ptr: pointer;Const Len: integer): string;
asm
    Push ebx
    push esi
    push edi
    test eax,eax
    jz   @@Exit
    mov  edi,eax
    mov  esi,ecx
    mov  ecx,edx
    push ecx
    add  edx,edx
    mov  eax,esi
    call System.@LStrSetLength //设置新串长度
    mov  eax,esi       //新字符串地址
    Call UniqueString  //产生一个唯一的新字符串,串位置在eax中
    pop  ecx
  @@SetHex:
    xor  edx,edx       //清空edx
    mov  dl, [edi]     //Str字符串字符
    mov  ebx,edx       //保存当前的字符
    shr  edx,4         //右移4字节,得到高8位
    mov  dl,byte ptr[edx+@@HexChar] //转换成字符
    mov  [eax],dl      //将字符串输入到新建串中存放
    and  ebx,$0F       //获得低8位
    mov  dl,byte ptr[ebx+@@HexChar] //转换成字符
    inc  eax             //移动一个字节,存放低位
    mov  [eax],dl
    inc  edi
    inc  eax
    loop @@SetHex

  @@Exit:
    pop  edi
    pop  esi
    pop  ebx
    ret
  @@HexChar: db '0123456789ABCDEF'
end;
//*************************************************************
//    名称: HexToBin                                       
//    功能: 将16进制字符串转换成二进制信息存入    
//    用法:                                                
//        Mem := TMemoryStream.Create;      
//        Mem.SetSize(100);                         
//        str := 'TEST';                               
//       writeSize := HeToBin(strToHex(Str),Mem.Memory,4);  
//*************************************************************
function HexToBin(HexStr: string;BinnryBuf: pointer;BufSize: integer): integer;
asm
  push  ebx
  push  edi
  Push  ecx
  mov   edi,ecx
  test  eax,eax
  Jz    @@Exit
  test  edx,edx
  Jz    @@Exit
  test  ecx,ecx
  Jz    @@Exit
  mov   edi,[eax-4]
  shr   edi,1   //长度除2获得二进制实际长度
  cmp   edi,ecx   //比较实际长度和给定长度
  JB    @@Belive  //给定长度大于实际长度,直接执行,否则使用给定长度
  mov   edi,ecx   //使用给定长度
@@Belive:
  xor   ecx,ecx
  mov   bh,[eax] //字符
  cmp   bh,'0'   //查看是否在0到f之间的字符
  JB    @@Exit   //小于0
  cmp   bh,'f'
  JA    @@Exit   //大于f跳
  sub   bh,'0'
  mov   cl,bh
  mov   bh,byte ptr[ecx+@@Convert]
  shl   bh,4
  xor   ecx,ecx
  inc   eax     //指针前移
  mov   bl,[eax]
  cmp   bl,'0'   //查看是否在0到f之间的字符
  JB    @@Exit   //小于0
  cmp   bl,'f'
  JA    @@Exit   //大于f跳
  sub   bl,'0'
  mov   cl,bl
  mov   bl,byte ptr[ecx+@@Convert]
  xor   ecx,ecx
  mov   cl,bh
  and   ebx,00FFh
  add   ebx,ecx
  mov   [edx],ebx
  inc   eax
  inc   dx
  dec   edi
  JNZ  @@Belive
@@Exit:
  Pop   eax
  sub   eax,edi
  pop   edi
  pop   ebx
  ret
@@Convert:  //包含大小写的ABCDEF数组列
  DB  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
  DB  -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
  DB  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  DB  -1,10,11,12,13,14,15
end;

{通过上面的PointToHex函数将内存流转换位16进制字符串}
function TIniFile.StreamToStr(Value: TStream): String;
begin
  result := PointToHex(TMemoryStream(Value).memory,Value.Size);
end;

{16进制串转换为流}
function TIniFile.StrToStream(const aStr: String;  Value: TStream): Integer;
Var
  Text: String;
  Stream: TMemoryStream;
  Pos: Integer;
Begin
  Text := aStr;
  If Text <> '' Then
  Begin
    If Value Is TMemoryStream Then
      Stream := TMemoryStream(Value)
    Else
      Stream := TMemoryStream.Create;
    Try
      Pos := Stream.Position;
      Stream.SetSize(Stream.Size + Length(Text) Div 2);      
      HexToBin(Text, Pointer(Integer(Stream.Memory) + Stream.Position), Length(Text) Div 2);
      Stream.Position := Pos;
      If Value <> Stream Then Value.CopyFrom(Stream, Length(Text) Div 2);
      Result := Stream.Size - Pos;
    Finally
      If Value <> Stream Then Stream.Free;
    End;
  End
  Else
    Result := 0;
end;

{读取流数据}
function TIniFile.ReadStream(const Section, aParamName: String;
  aValue: TStream): Integer;
Var
  mValue: String;
begin
  mValue := ReadString(Section,aParamName, '');
  Result := StrToStream(mValue, aValue);
end;

{写入流数据}
procedure TIniFile.WriteStream(const Section, aParamName: String;
  aValue: TStream);
Var
  mValue: String;
Begin
  mValue := StreamToStr(aValue);
  WriteString(Section,aParamName, mValue);
end;

你可能感兴趣的:(Delphi向Ini文件中写入流数据)