TMemoryStream 操作的效率问题(200分)

  • 主题发起人 主题发起人 S3D4
  • 开始时间 开始时间
procedure AddStream(Source, Dest: TMemoryStream);
var
SourceSize, DestSize: Integer;
begin
DestSize := Dest.Size;
SourceSize := Source.Size;
Dest.Size := DestSize + SourceSize;
Move(Source.Memory^, Pointer(Integer(Dest.Memory) + DestSize)^, SourceSize)

end;

procedure DeleteStream(Stream: TMemoryStream
StartPosition, EndPosition: Integer);
var
P: Pointer;
Count: Integer;
begin
P := Stream.Memory;
Count := Stream.Size;
if Count > EndPosition then
begin
Move(Pointer(Integer(P) + EndPosition)^, Pointer(Integer(P) + StartPosition)^, Count - EndPosition);
Stream.Size := Stream.Size - (EndPosition - StartPosition);
end
else
Stream.Size := StartPosition;
end;

大概是这样吧,随手写的,没调,自己调整吧。
 
copy_paste 兄,基本代码我已经搞定,我现在的疑惑在于 修改 TMemoryStream 的 Size 是否
会造成内存泄漏,如果会(我想应该会的)?如何处理

您的 AddStream 如何保证 Dest 后面的内存区域是没有分配的,这样直接 Append Source
Stream 会不会造成混乱?

 
to S3D4:

你说的很对,Delphi中的字符串的后面也都有一个#0,这也是Delphi的字符串
可以直接用PChar(S),作为API函数的参数的原因,
但这是为了和C String相兼容,Delphi的字符串中间是可以有#0的,
并且后面的数据也不会被丢掉,字符串的实际长度是由一个长度字段来决定的

如果用字符串,有现成的函数,你的问题也就不是问题了,
同时,代码会更简洁,更易懂,
你可以试着写一下,看看到底哪种方法简单
 
procedure AddStream(Source, Dest: TMemoryStream);
var
SourceSize, DestSize: Integer;
begin
DestSize := Dest.Size;
SourceSize := Source.Size;
Dest.Size := DestSize + SourceSize;
Move(Source.Memory^, Pointer(Integer(Dest.Memory) + DestSize)^, SourceSize)

end;
Memory指向的是流的首指针,当Size改变时,通过GlobalReAllocPtr重新分配一个Size的
内存空间,并保证原有的数据不丢失,新分配的空间为可移动的,为0的空间,我看VCL源码
是这样写的。
Dest.Size := DestSize + SourceSize;
为Dest分配了一个Dest.Size + Source.Size的空间,Dest原来的数据在Dest.Size中,Source
的数据为空,在Dest的SourceSize空间中。
Move(Source.Memory^, Pointer(Integer(Dest.Memory) + DestSize)^, SourceSize)

将Source.Memory赋值到Dest那一片刚申请的空间中,
Pointer(Integer(Dest.Memory) + DestSize)^
上面的Dest.Memory 为首地址,DestSize为原来Dest的内存大小,那么上面的计算出来地址
就是Dest为增加Source内存的后继地址了。然后将Source.Memory赋值到Dest中。完成。

一般流的操作就是Size, Memory操作,只在Memory的操作在Size的范围内,一般不会有问题,
总是很小心的,呵。
 
谢谢诸位的激情参与,我准备将该贴冷却一段时间,明天我再来
 
你可以使用动态数组
array of byte;或者array of char;
例如
Type
Tmem=Record;
First:PByte;//每次分配Buffer时都要指向Buffer[0]
Pos:LongInt;//当前元素的索引
Buffer:array of Byte;//要操作的内存
end

进一步可以扩充成一个类,不就是自己写一个Stream了么。
 
这个站上有个讲座<谈Delphi编程中“流”的利用>,大家学习学习:
http://www.codelphi.com/channel/jsjn/read.asp?ano=850
 
如 copy_paste 所言,VCL 原码中的确显示更改 Size 会重新分配内存,但是效率提高并
不大,估计是因为频繁在堆里面开辟释放大量空间造成,郁闷中... ...

LiChaoHui 的方法也的确可以,开发效率高,但是运行效率更加不好,另外在特征字符串
查找是含有 0 的字符串,比如 AnsiStrPos 时 Search #00#00#01#B3 就不行了,因为含有
#0,可能是作为String结尾处理了,具体没有看VCL

wr960204 建议用数组,嗯,没有错,我计划用环形数组模型来试试效率,不过改动过大,
更加 郁闷中 ... ...

其它诸位参与有功,在此多谢
 
多人接受答案了。
 
你也真是,用Pos 多好,谁让你用AnsiStrPos的?
 
后退
顶部