======================================================
注:本文源代码点此下载
======================================================
tmemorystream对象是一个管理动态内存中的数据的stream对象,它是从tcustommemorystream中继承下来的,除了从tcustommemorystream中继承的属性和方法外,它还增加和覆盖了一些用于从磁盘文件和其它注台读数据的方法。它还提供了写入、消除内存内容的动态内存管理方法。下面介绍它的这些属性和方法。
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将成为文件内容在内存中的完整拷贝。
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中。
======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/