delphi-TMemoryStream用法

var
  FileName:string;
  memoryS:TMemoryStream;
  dataPort:Cardinal; //整型 无符号32位
  dataNum:Word;
  i:Integer;
  StrList:TStringList;
  Buffer1,Buffer2:array[0..69] of Char;
begin
  FileName:='a:\数据文件.cfg';
  if not FileExists(FileName) then Exit;
  try
    memoryS := TMemoryStream.Create;
    StrList:=TStringList.Create;
    memoryS.LoadFromFile(FileName);
    dataNum:=memoryS.Size DIV 120 ;
    mmo1.Lines.Add(IntToStr(dataNum));
    FOR i:=0 to dataNum-1 do  begin
      dataPort:=i*120; 
      memoryS.Position :=dataPort; //设置读取位置
      memoryS.ReadBuffer(Buffer1,50);
      mmo1.Lines.Add(IntToStr(dataPort)+'--->>'+Buffer1);
      dataPort:=dataPort+50;  //偏移位置
      memoryS.Position :=dataPort;
      memoryS.ReadBuffer(Buffer2,70);    //读取数据到Buffer2
      mmo1.Lines.Add(IntToStr(dataPort)+'--->>'+Buffer2);
      StrList.Add(StrPas(Buffer1)+','+StrPas(Buffer2));   //Char 转换string 格式如下StrPas(string)
    end;
   mmo1.Text:=(StrList.Text);
  finally
   memoryS.free;
   StrList.free;
  end;
end;

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

20.1.5.1 TMemoryStream的属性和方法

  1. Capacity属性
    声明:property Copacity: Longint;
    Capacity属性决定了分配给内存流的内存池的大小。这与Size属性有些不同。Size属性是描述流中数据的大小。在程序中可以将Capacity
    的值设置的比数据所需最大内存大一些,这样可以避免频繁地重新分配。
  2. Realloc方法
    声明:function Realloc(var NewCapacity: Longint): Pointer; virtual;
    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将成为文件内容在内存中的完整拷贝。

20.1.5.2 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对象方法的实现
⑴ 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则触发内存流错的异常事件,否则返回指向分配的内存的指针。
⑵ 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;

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

procedure TMemoryStream.Clear;
begin
SetCapacity(0);
FSize := 0;
FPosition := 0;
end;

⑷ 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中。

已标记关键词 清除标记
相关推荐
不需Excel也可讀寫xls檔的Delphi控件 用来读取Excel,Access的控件 读写任何单元值 数字型、字符型、布尔型以及错误型。但是你了解日期和时间型单元吗?在Excel中没有这样的单元。Excel是和Delphi一样的方式来存储日期和时间的,即浮点型。那是什么制造了日期或时间值啦,是格式化。 完全支持公式。你可以使用和Excel一样的函数,也支持对外部工作簿引用的公式,你甚至可以从外部引用读取结果。 与操作Delphi的TStringGrid一样的方式操作单元格,或则通过给单元格命名,比如:”D7” 根据单元格的规则以字符串格式读取单元值 根据你的需求格式化单元 格式化很简单。通过获取单元格,你就可以操作单元的格式属性。例如:XLSReadWriteII.Sheet[n].Cell[Col,Row].FontSize := 12; 你也可以对域进行格式化,比如设置边框。 支持所有的Excel格式选项 合并单元格 操作所有的打印选项 选择页面大小,设置边距 设置标题和页脚,包括格式码。 定义打印区域 设置分页符 XLSReadWriteII完全支持Unicode 所有的字符型都是宽字符型。你完全不必担心非英语字符。 控件 你可以插入控件以及定义他们的源和目的单元 绘图 插入所有种类的绘图,从简单的线条到AutoShapes 多行文本和文本框 创建和编辑文本框以及多行文本 图表 创建和Excel中一样选项的图表 复制/移动/删除 可以以Excel一样的行为复制、移动和删除单元 行列也可以像单元一样复制和移动 支持工作簿之间的复制和移动 可以复制整个工作簿 使用命名的域/单元 你可以在你想要的任何地方命名 通过命名访问单元格,例如:XLS.NameAsFloat['MyCell'] := 202.5; 支持指定、内置的名称 支持所有超链接类型 网页和E-mail地址 本地文件 服务器文件 工作薄引用 加密文档 你可以读写加密文件。条件是你需要知道文件的密码。 计算 可计算单元以及整个工作薄 计算引擎将依据单元进行计算。 可读取引用的外部工作薄。这通过一个特殊的快速查询程序进行执行 Rich Text单元 为了轻松地创建多字体格式的单元,单元可以以RTF格式读写 VBA宏 可以读写文件中的宏,使用XLSReadWriteII可以为控件比如:按钮、组合框等添加宏 导入及导出 从下列导入数据… Open Office Calc文档 CSV文件以及其他可以自动识别分隔符、小数分隔符和文本引用字符的文本文件 HTML表格(<TABLE>标签) 数据库 导出数据为… CSV文件 HTML文件 其他 自动过滤 单元验证 有条件的格式 合并单元 PaintCell方法:将单元内容渲染到TCanvas对象的 XLSReadWriteII包还包含下列组件: 从任何数据库中导入数据到工作薄 工作薄导出为HTML文件
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页