问题: TMemoryStream 操作的效率问题 ( 积分: 200 )
分类: Object Pascal
来自: S3D4, 时间: 2002-12-26 9:03:00, ID: 1538069
谁知道 TMemoryStream 如何插入、删除 TStream 操作,我需要大量 Stream 操作,关键是
如何在不建立临时 MemoryStream 进行 CopyForm 操作,因为 Stream 非常大,有几十 M,
操作又非常平凡,要达到实时操作,所以需要考虑效率问题
procedure AddStream(var TMemoryStream, TStream, InsertPosition);
procedure DeleteStream(var TMemoryStream, StartPosition, EndPosition);
来自: 一生中最爱, 时间: 2002-12-26 9:11:00, ID: 1538100
up
来自: form1., 时间: 2002-12-26 9:13:00, ID: 1538111
up
来自: LiChaoHui, 时间: 2002-12-26 9:13:00, ID: 1538114
TMemoryStream操作的速度是很快的,
但是如果太大,则最好使用文件流
来自: S3D4, 时间: 2002-12-26 9:19:00, ID: 1538150
我试过,在 P4 1.6+512M的机器里面操作(其实是网络媒体截获流),延迟很厉害,所以问问
如何直接内存操作进行 MemoryStream 的插入、删除
来自: coolmy, 时间: 2002-12-26 9:30:00, ID: 1538225
To S3D4:也是关于流的问题
烦请相助 http://www.delphibbs.com/delphibbs/dispq.asp?lid=1535254
来自: S3D4, 时间: 2002-12-26 9:42:00, ID: 1538291
我自己还是半桶水,你还敢让我帮你?
来自: Kelvin_zillion, 时间: 2002-12-26 9:55:00, ID: 1538364
对TMemoryStream.Memory直接操作?
不过我觉得这样不好。
能不能说说你要实现的功能,看看有没有别的解决办法。
来自: S3D4, 时间: 2002-12-26 10:06:00, ID: 1538367
这是我自己写的,好像有问题,高手们看看吧
procedure DeleteMemoryStream(var Stream: TMemoryStream; StartPosition, EndPosition: Int64);
var
PSource, PDest: ^Byte;
begin
PSource:= Stream.Memory;
Inc(PSource, StartPosition);
PDest := PSource;
Inc(PDest, EndPosition - StartPosition);
System.Move(PSource^, PDest^, Stream.Size - EndPosition);
// Windows.MoveMemory
end;
InsertMemoryStream 我就不知道如何写了,谁能帮手?
来自: LiChaoHui, 时间: 2002-12-26 10:10:00, ID: 1538445
用字符串来操作吧,完全可以满足你的要求,
并且还有标准的函数可以调用
procedure Delete(var S: string; Index, Count:Integer);
procedure Insert(Source: string; var S: string; Index: Integer);
字符串最大可以达到2GB,操作起来方便,也不会有内存泄漏
最好的解决方法了
来自: S3D4, 时间: 2002-12-26 10:33:00, ID: 1538549
LiChaoHui 兄说笑了,我这里大量基于 PByte 的位移、异或操作怎么办,16 进制数据查找
怎么办呢?
来自: wr960204, 时间: 2002-12-26 10:47:00, ID: 1538610
你刚才写删除过程没有改变流的Size属性,到时候会有问题的。
如果你嫌弃流的操作慢,为何不自己从头包装一个呢?
给你几个API
CopyMemory(MoveMemory)
FillMemory
GetMemory
来自: S3D4, 时间: 2002-12-26 10:51:00, ID: 1538628
Delphi的帮助里面说过,更改TStream的size属性没有意义,所以没有改动,不过让我试试
来自: ymf, 时间: 2002-12-26 11:02:00, ID: 1538670
学习
来自: LiChaoHui, 时间: 2002-12-26 11:04:00, ID: 1538680
这位老兄,我绝对没有说笑,很严肃的!!
你可以定义一个PByte的指针, var PData: PByte;
然后,取字符串首地址,转化为PByte类型
PData := PByte(PChar(S)); //注意,一定要这样写
对于PByte,你做什么操作应该都可以的,移位,异或,
至于查找,用字符串操作函数效率更高
function Pos(Substr: string; S: string): Integer;
我相信,用字符串操作绝对没有问题,有现成的函数可用,
效率更高,也不用分配内存和释放内存,不用担心内存泄漏,
之所以能够这样,是因为Delphi中的字符串,是不同于c中的字符串的,
他不是0结尾的,不用担心会丢失0后面的东西
字符串查找Pos也能够处理#0字符,不信你可以试试
如果字符串可以解决你的问题,把你的200分全给我!
我相信绝对可以!这是最好的解决方法了
来自: S3D4, 时间: 2002-12-26 11:05:00, ID: 1538682
试验证明修改 TMemoryStream Size 属性的确有效,请问wr960204,
这种操作会有什么问题的 ???
来自: jsxjd, 时间: 2002-12-26 11:05:00, ID: 1538685
插入就意味着移动,要尽量避免插入
来自: S3D4, 时间: 2002-12-26 11:08:00, ID: 1538689
LiChaoHui 兄,不要恼火,我的代码基本已经定型,你让我做如此改动是不是要杀了我,我
现在只考虑在现有基础上做轻微改动来提高效率,当然如果还是不理想我会考虑您的建议,
至于这 200 分,身外之物,,大家共同探讨,不必太过执着吧
来自: S3D4, 时间: 2002-12-26 11:12:00, ID: 1538707
LiChaoHui 兄,Delphi 里面的字符串 AnsiString 也是 chr(0) 结尾的,印象里面它的内
存架构和 PChar 相似,只是在String 的首部多了一个标志位表明 String 的长度,也许有
错,欢迎指正
来自: lovered, 时间: 2002-12-26 11:16:00, ID: 1538733
Move的意思是拷贝内存,但是丢弃的如何做?它给你自动丢掉了吗?自己写个TMemoryStream吧?不要偷懒!^_^
来自: copy_paste, 时间: 2002-12-26 11:17:00, ID: 1538735
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;
大概是这样吧,随手写的,没调,自己调整吧。
来自: S3D4, 时间: 2002-12-26 11:25:00, ID: 1538762
copy_paste 兄,基本代码我已经搞定,我现在的疑惑在于 修改 TMemoryStream 的 Size 是否
会造成内存泄漏,如果会(我想应该会的)?如何处理
您的 AddStream 如何保证 Dest 后面的内存区域是没有分配的,这样直接 Append Source
Stream 会不会造成混乱?
来自: LiChaoHui, 时间: 2002-12-26 11:29:00, ID: 1538799
to S3D4:
你说的很对,Delphi中的字符串的后面也都有一个#0,这也是Delphi的字符串
可以直接用PChar(S),作为API函数的参数的原因,
但这是为了和C String相兼容,Delphi的字符串中间是可以有#0的,
并且后面的数据也不会被丢掉,字符串的实际长度是由一个长度字段来决定的
如果用字符串,有现成的函数,你的问题也就不是问题了,
同时,代码会更简洁,更易懂,
你可以试着写一下,看看到底哪种方法简单
来自: copy_paste, 时间: 2002-12-26 11:40:00, ID: 1538847
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的范围内,一般不会有问题,
总是很小心的,呵。
来自: S3D4, 时间: 2002-12-26 11:40:00, ID: 1538848
谢谢诸位的激情参与,我准备将该贴冷却一段时间,明天我再来
来自: wr960204, 时间: 2002-12-26 12:38:00, ID: 1539016
你可以使用动态数组
array of byte;或者array of char;
例如
Type
Tmem=Record;
First
Byte;//每次分配Buffer时都要指向Buffer[0]
Pos:LongInt;//当前元素的索引
Buffer:array of Byte;//要操作的内存
end;
进一步可以扩充成一个类,不就是自己写一个Stream了么。
来自: windbell, 时间: 2002-12-26 16:08:00, ID: 1539897
这个站上有个讲座<谈Delphi编程中“流”的利用>,大家学习学习:
http://www.codelphi.com/channel/jsjn/read.asp?ano=850
来自: S3D4, 时间: 2002-12-27 12:16:00, ID: 1542051
如 copy_paste 所言,VCL 原码中的确显示更改 Size 会重新分配内存,但是效率提高并
不大,估计是因为频繁在堆里面开辟释放大量空间造成,郁闷中... ...
LiChaoHui 的方法也的确可以,开发效率高,但是运行效率更加不好,另外在特征字符串
查找是含有 0 的字符串,比如 AnsiStrPos 时 Search #00#00#01#B3 就不行了,因为含有
#0,可能是作为String结尾处理了,具体没有看VCL
wr960204 建议用数组,嗯,没有错,我计划用环形数组模型来试试效率,不过改动过大,
更加 郁闷中 ... ...
其它诸位参与有功,在此多谢
来自: S3D4, 时间: 2002-12-27 12:17:00, ID: 1542055
多人接受答案了。
来自: LiChaoHui, 时间: 2002-12-27 14:31:00, ID: 1542503
你也真是,用Pos 多好,谁让你用AnsiStrPos的?
得分大富翁: coolmy-5,copy_paste-100,form1.-5,jsxjd-5,Kelvin_zillion-5,LiChaoHui-30,lovered-5,windbell-5,wr960204-30,ymf-5,一生中最爱-5,