`

delphi TMemoryStream对象用法

 
阅读更多
TMemoryStream对象


TMemoryStream对象是一个管理动态内存中的数据的Stream对象,它是从TCustomMemoryStream中继承下来的,除了从TCustomMemoryStream中继承的属性和方法外,它还增加和覆盖了一些用于从磁盘文件和其它注台读数据的方法。它还提供了写入、消除内存内容的动态内存管理方法。下面介绍它的这些属性和方法。

TMemoryStream的属性和方法

1.Capacity属性

声明:property Copacity:Longint;

   Capacity属性决定了分配给内存流的内存池的大小。这与Size属性有些不同。Size属性是描述流中数据的大小。在程序中可以将Capacity的值设置的比数据所需最大内存大一些,这样可以避免频繁地重新分配

2.Realloc方法

声明:function Realloc(var NewCapacity: Longint): Pointer;

   Realloc方法,以8K为单位分配动态内存,内存的大小由NewCapacity指定,函数返回指向所分配内存的指针。

3.SetSize方法

   SetSize方法消除内存流中包含的数据,并将内存流中内存池的大小设为Size字节。如果Size为零,是SetSize方法将释放已有的内存池,并将Memory属性置为nil;否则,SetSize方法将内存池大小调整为Size。

4.Clear方法

声明:procedure Clear;

  Clear方法释放内存中的内存池,并将Memory属性置为nil。在调用Clear方法后,Size和Position属性都为0。5.LoadFromStream方法

声明:procedure LoadFromStream(Stream: TStream);

    LoadFromStream方法将Stream指定的流中的全部内容复制到MemoryStream中,复制过程将取代已有内容,使MemoryStream成为Stream的一份拷贝。

6.LoadFromFile方法

声明:procedure LoadFromFile(count FileName: String);

   LoadFromFile方法将FileName指定文件的所有内容复制到MemoryStream中,并取代已有内容。调用LoadFromFile方法后,MemoryStream将成为文件内容在内存中的完整拷贝。

 

TMemoryStream对象的实现原理

TMemoryStream从TCustomMemoryStream对象直接继承,因此可以享用TCustomMemoryStream的属性和方法。前面讲过,TCustomMemoryStream是用于内存中数据操作的抽象对象,它为MemoryStream对象的实现提供了框架,框架中的内容还要由具体MemoryStream对象去填充。TMemoryStream对象就是按动态内存管理的需要填充框架中的具体内容。

下面介绍TMemoryStream对象的实现。

1.TMemoryStream属性的实现 TMemoryStream在其protected部分增加了一个Capacity属性,该属性决定了MemoryStream所占动态内存的大小。TMemoryStream首先在private部分声明了FCapacity变量作为存储Capacity属性值的数据域,然后在protected部分声明了该属性。在属性声明的读控制部分简单读取FCapacity的值,在写控制处调用了方法SetCapacity。该方法除了给FCapacity赋值外还执行了修改Capacity属性所必需操作如状态改变等。

下面是属性的实现:

TMemoryStream = class(TCustomMemoryStream)

    private

       FCapacity: Longint;

       procedure SetCapacity(NewCapacity: Longint);

    protected

       property  Capacity: Longint read FCapacity write SetCapacity;

    public

end;

写控制方法SetCapacity的实现是这样的 :

procedure TMemoryStream.SetCapacity(NewCapacity: Longint);

begin

    SetPointer(Realloc(NewCapacity), FSize);

    FCapacity := NewCapacity;

end;

在SetCapacity 方法先是调用Realloc重新分配内存,然后用NewCapacity的值给FCapacity赋值。Realloc方法进行某些对象状态的改变。

2.TMemoryStream对象方法的实现

   (1)Realloc方法 Realloc方法是TMemoryStream动态内存分配的核心,它的SetSize、SetCapacity等方法最终都是调用Realloc进行内存的分配和初始化工作的。它的实现如下:

const
    MemoryDelta = $2000;

function TMemoryStream.Realloc(var NewCapacity: Longint): Pointer;

begin

    if NewCapacity > 0 then

       NewCapacity := (NewCapacity + (MemoryDelta - 1)) and not (MemoryDelta - 1);  

       Result := Memory;

   if NewCapacity <> FCapacity then

   begin

      if NewCapacity = 0 then

      begin

          GlobalFreePtr(Memory);

          Result := nil;

      end

      else

      begin

         if Capacity = 0 then

            Result := GlobalAllocPtr(HeapAllocFlags, NewCapacity)

         else

            Result := GlobalReallocPtr(Memory, NewCapacity, HeapAllocFlags);

         if Result = nil then

         raise EStreamError.CreateRes(SMemoryStreamError);

      end;

    end;

end;

Realloc方法是以8K为单位分配动态内存的,方法中的第一句if语句就是执行该操作。如果传入的NewCapacity参数值为0,则释放流中的内存。Realloc方法用GLobal  FreePtr函数释放内存,用GlobalAllocPtr分配内存,用GlobalReallocPtr进行内存的重分配。如果原来的Capacity属性值为0,则调用Globa|AllocPtr否则调用GlobalReallocPtr。最后如果Result为nil则触发内存流错的异常事件,否则返回指向分配的内存的指针。

   (2)Write方法 Write方法从内存流内部缓冲池的当前位置开始写入二进制数据。其实现如下:

function TMemoryStream.Write(const Buffer; Count: Longint): Longint;

var

   Pos: Longint;

begin

   if (FPosition >= 0) and (Count >= 0) then

   begin

       Pos := FPosition + Count;

       if Pos > 0 then

       begin

          if Pos >FSize then

          begin

              if Pos > FCapacity then

                 SetCapacity(Pos);

                 FSize := Pos;

              end;

              System.Move(Buffer, Pointer(Longint(FMemory) + FPosition)^, Count);

              FPosition := Pos;

              Result := Count;

              Exit;

           end;

        end;

        Result := 0;  

    end;

end;

Buffer中存储要写入流的二进制数据,如果要写入的数据的字节超出了流的内存池的大小,则调用SetCapacity方法再分配内存,然后用内存复制函数将Buffer中的数据复制到FMemory中。接着移动位置指针,并返回写入数据的字节数。分析这段程序可以知道,FCapacity的值和FSize的值是不同的。

    (3)Clear方法

Clear方法消除内存流中的数据,将Memory属性置为nil,并将FSize和FPosition 的值设为0。其实现如下:

procedure TMemoryStream.Clear;

begin

    SetCapacity(0);

    FSize := 0;

    FPosition := 0;

end;

    (4)LoadFromStream和LoadFromFile方法 LoadFromStream方法首先根据传入的Stream的Size属性值重新分配动态内存,然后调用Stream的ReadBuffer方法往FMemory中复制数据,结果Stream的全部内容在内存中有了一份完整拷贝。其实现如下:

procedure TMemoryStream.LoadFromStream(Stream: TStream);

var

   Count: Longint;

begin

    Stream.Position := 0;

    Count := Stream.Size;

    SetSize(Count);

    if Count <> 0 then

      Stream.ReadBuffer(FMemory^, Count);

end;
LoadFromFile与LoadFromStream是一对方法。LoadFromFile首先创建了一个TFileStream对象,然后调用LoadFromStream方法,将FileStream文件流中的数据写入MemoryStream中。

分享到:
评论

相关推荐

    利用Delphi的TMemoryStream实现文件起始位置添加文件头

    利用Delphi的TMemoryStream实现文件起始位置添加文件头

    delphi实现保存和读取图片的方法

    主要介绍了delphi实现保存和读取图片的方法,主要包括了显示图片、保存图片和读取图片的实现方法,是非常实用的技巧,需要的朋友可以参考下

    delphi TSteam系列技术

    有关Delphi中TStream流技术的总结 包括TMemoryStream、TFileStream流等等

    Delphi将bmp存取到流中

    Delphi将bmp存取到流中,适合初学者理解TmemoryStream

    Delphi中文件流的基础使用方法四个实例

    TMemoryStream(内存流) 入门 TFileStream(文件流) 读写 TMemoryStream(内存流)读取文件 遍历读取流中的所有数据

    Delphi 样例-动态数组和静态数组.rar

    Delphi样例代码:演示动态数组、静态数组、TBytes 的区别,以及结合TMemoryStream的使用

    DELPHI网络聊天

    MyStream := TMemoryStream.Create; try MyStream.Write(TmpStr[1], Length(Edit1.Text)); if ListBox1.ItemIndex=0 then begin for i:=1 to ListBox1.Items.Count-1 do //如果选择"大家",则对所有的网友发送信息 ...

    Delphi开发技巧之-System

    使用TMemoryStream保存数据 使用未注册字体 使用注册表读写字符串 使系统菜单关闭按钮失效 列举注册表键 列举运行的进程 列出所有登录到工作站的用户信息 创建精确定时器 取CPU名称 取windows, system, temporary ...

    NATIVEXML DELPHI2010

    binstream2: TMemoryStream; binstream2.WriteBuffer(Pointer(Text)^, len); 与 binstream2.WriteBuffer(Text, len); 有什么区别,一个有问题,一个就一切正常,我再这里卡主很长时间。 查了一下定义 procedure ...

    MMTools控件的demo例子,包含从TMemoryStream内存流,资源中播放MP3

    MMTools控件的demo例子,包含从TMemoryStream内存流,资源中加载mp3。具体例子在\mpeg\memstream中

    IdTCPServer、IdTCPClient 实例 Indy 10.6.2 编译平台Delphi10.2.2

    主要例子:发送IdBytes结构型Record数据、TMemoryStream流发送、发送图片、发送Tstrings、发送整型数值、发送文件等等功能,Tstream流发送未完成,不是太懂Tstream的操作性质,望大神分享技巧 Indy组件版本:10.6.2 ...

    delphi压缩后并使用http协议base64上传下载6G超大文件的演示即核心代码概要.mp4

    知识点:1、Delphi自带的压缩解压单元system.zlib.pas中核心函数的使用;2、服务端http协议ContentType(mime-type)相关列表类型的注册;3、Base64编码的规则;4、为何要分块断点续传,并使用TFileStream文件流替代...

    一个读取速度超快的filestream-TFastFileStream

    首先,要解决的是打开大文件慢的问题,对于这个,使用MapViewOfFile&#40;&#41;,将文件直接当作内存镜像来访问就可以了,关于MapViewOfFile&#40;&#41;,以及文件内存镜像,可以参考这篇文章:...

    个读取速度超快的FileStream

    将TFileStream中的一部分再复制给TMemoryStream,这个复制过程会开辟新的内存再进行复制,理所当然内存大了,复制时间也会变长。 我决心针对目前我所遇到的问题,再写一个文件读取类,目前就叫TFastFileStream吧,...

    PE资源修复

    相对复杂性,要求使用者对 PE 结构必须十分属性,因此本功能仅适合高级用户使用。 &lt;1&gt; 输出函数 DumpResFromFile C 形式函数原型: BOOL __stdcall DumpResFromFile&#40;const char* PEFile, char* ResFile, ...

    DIZipWriter 6.3.0 for D7-XE10.2

    DIZipWriter is a component for Delphi (Embarcadero / CodeGear / Borland) to create PKZip-compatible ZIP archives. New ZIP archives may be created as files, as streams, or even entirely in memory using...

    DIZipWriter 6.2.1 D4-XE10.1 Full Source

    DIZipWriter is a component for Delphi (Embarcadero / CodeGear / Borland) to create PKZip-compatible ZIP archives. New ZIP archives may be created as files, as streams, or even entirely in memory using...

    更换exe图标_IDo_图标_换图标_

    Src grpic : TMemoryStream; id : ICONINFORMATION; ih : ICONHEADER; ic : ICONDIRENTRYCOMMON; hinst : LongInt; oldentry : Int64;begin Result := False; Src := TMemoryStream.Create; grpic := TMemoryStream...

    DIZipWriter v5.5.0 Full Sources

    DIZipWriter is a Delphi component to create PKZip-compatible ZIP archives. Archive output is completely stream-based and works with any TStream descendant. DIZipWriter therefore direclty writes to ...

    DIZipWriter v6.2.0 for D7-XE10.1 ZIP 压缩 解压缩

    DIZipWriter is a Delphi component to create PKZip-compatible ZIP archives. Archive output is based on TStream and writes directlyfiles (TFileStream), memory (TMemoryStream), or database BLOBs...

Global site tag (gtag.js) - Google Analytics