替换Tmemorystream中的部分内容的速度问题(50分)

  • 主题发起人 主题发起人 laimama
  • 开始时间 开始时间
L

laimama

Unregistered / Unconfirmed
GUEST, unregistred user!
想要在Tmemorystream中替换部分字符,现在采用临时Tmemorystream的方法,一个一个字节的读取、判断、写入,速度太慢了,大家有速度更快的方法吗?
 
也许开几个线程会快一点?
 
多线程不会加快的。

用块读写。一次读一块数据出来。处理好了。再一次写入。
 
问题: 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:PByte;//每次分配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,
 
to weiliu:看了半天,没有受到启发:),感谢了!
 
接受答案了.
 

Similar threads

后退
顶部