导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
2022/1/17 13:29:02
标题:
加入我的收藏
楼主:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 14:17:07
1楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 14:26:51
2楼:
高手们回答次数太多都懒得回答已有的。
----------------------------------------------
[alias] co = clone --recurse-submodules up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/ >http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
2022/1/17 14:30:58
3楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 16:05:01
4楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 16:31:49
5楼:
AnsiString 与 Unicode string内存结构区别很大, 简单讲 Unicode string 一个字符总是两个字节, AnsiString 则有可能是1个,2个,3个. 因此处理 Unicode string 更简单更有效率. 但是如果使用了汇编在字节层面来操作字符串, 那处理ansi string的汇编代码基本上是没有可能简单移植到unicode string上来的. 建议你使用 pos定位然后复制的方法来实现一个自己的 StringReplace, pos的效率杠杠的.
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
2022/1/17 17:01:38
6楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 17:29:51
7楼:
试试mormot的stringreplaceall这个方法
----------------------------------------------
-
作者:
2022/1/17 17:41:15
8楼:
不知道你说的几百KB就要10秒以上是怎么得来的。 我在VMWare虚拟机里面,Delphi11测试。 1.7MB大的字符串,stringreplace 1000次的测试结果。 var s,t : string; c, i : Integer; begin // s := System.IOUtils.TFile.ReadAllText('c:\program files (x86)\embarcadero\studio\22.0\source\rtl\win\Winapi.Windows.pas'); //s 内容1.7MB c := GetTickCount; for i := 0 to 1000-1 do begin t := StringReplace(s, 'windows', 'w', [rfReplaceAll]);//1000次1秒 //t := StringReplace(s, 'windows', 'w', []);//1000次0.5秒 //t := StringReplace(s, 'windows', 'w', [rfReplaceAll, rfIgnoreCase]);//1000次7秒 end; c := GetTickCount - c; Caption := c.ToString; end;
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2022/1/17 18:25:28
7楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 18:26:57
9楼:
这个不行???????
----------------------------------------------
[alias] co = clone --recurse-submodules up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/ >http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
2022/1/17 18:45:59
7楼:
你修改之后能用, 是因此系统先将unicode string转换成ansi string,然后旧代码可以正常工作了,然后 再将结果ansistring转换成unicode string, 这两次转换都是非常费时的,特别是涉及到非英文字符时,基本上没有什么取巧,都是一个一个字符查表处理. StringReplace我看了,写得已经很高效了.因此我觉得不应该它的问题. 可能还是你不小心导致了自动编码转换. 如果你能放出一个demo, 也许我可以帮你看看.
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
2022/1/17 18:47:05
9楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
此帖子包含附件: 大小: 587.9K
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 18:59:00
10楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
此帖子包含附件: 大小: 635.6K
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 19:14:19
11楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 20:06:19
12楼:
吧数据发出来 别人才可以测试。不然都是口水
----------------------------------------------
-
作者:
2022/1/17 20:22:47
13楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 20:43:53
15楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 21:02:38
16楼:
procedure TForm1.Button1Click(Sender: TObject); var sl:TStringList; tmp,t2:string; t,i:Integer; begin sl:= TStringList.Create; sl.LoadFromFile('test2.txt'); tmp:=sl.Text; t := GetTickCount(); for I := 0 to 100 do t2 := StringReplace(tmp,'人','★',[rfReplaceAll, rfIgnoreCase]); t := GetTickCount()-t; ShowMessage( Format( '%.4f',[t/1000.0] ) ); //执行100次,用时2.26秒 end;
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
2022/1/17 21:05:52
17楼:
用你的测试数据, 但你发出来的是gb2312, 我是先转换成 ucs 2 le bom格式再保存为test2.txt的 因此,最大可能还是你没有用对
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
2022/1/17 21:35:43
18楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 21:59:04
19楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/17 22:33:38
18楼:
楼主, 我用你的例子数据,就是60多MB的文本试了一下,替换所有“人”字为“★”。 我这里大概只用了1.4秒 多。 用的是你原始文件,GB2312 ,或者GBK ,或者GB18030 编码(这个没有影响)。 从文件里面读一行出来,替换后写入新的文件,直到写完。 没有加什么缓存。String 和AnsiString 都试了,时间上没什么区别。 所以我估计慢不在替换,而是字符串(过大)的处理不一样吧。 毕竟Delphi11早已跨平台了,而Delphi7不用考虑别的平台,也不用管unicodestring,widestring。 代码: procedure TForm3.Button1Click(Sender: TObject); var inFile:TEXTFILE; outFile:TEXTFILE; aLine,replaceLine,inFileName,outFileName:String; t:Integer; begin t := GetTickCount(); inFileName:= 'D:\Download\****ddd.txt'; outFileName:= 'D:\Download\****out.txt'; if FileExists(outFileName) then DeleteFile(outFileName); FileClose(FileCreate(outFileName)); AssignFile(outFile,outFileName,936); Rewrite(outFile); AssignFile(inFile,inFileName,936); Reset(inFile); while not EOF(inFile) do begin ReadLn(inFile,aLine); replaceLine:=StringReplace(aLine,'人','★',[rfReplaceAll]); WriteLn(outFile, replaceLine); end; CloseFile(inFile); CloseFile(outFile); t := GetTickCount()-t; //1.4210 秒 ShowMessage( Format( '%.3f秒',[t/1000.0] ) ); end; procedure TForm3.Button2Click(Sender: TObject); var inFile:TEXTFILE; outFile:TEXTFILE; aLine,replaceLine:AnsiString; inFileName,outFileName:String; t: TDateTime; begin t := Now(); inFileName:= 'D:\Download\****ddd.txt'; outFileName:= 'D:\Download\****out.txt'; if FileExists(outFileName) then DeleteFile(outFileName); FileClose(FileCreate(outFileName)); AssignFile(outFile,outFileName,936); Rewrite(outFile); AssignFile(inFile,inFileName,936); Reset(inFile); while not EOF(inFile) do begin ReadLn(inFile,aLine); replaceLine:= System.AnsiStrings.StringReplace(aLine,'人','★',[rfReplaceAll]); WriteLn(outFile, replaceLine); end; CloseFile(inFile); CloseFile(outFile); ShowMessage( Format( '%d毫秒',[System.DateUtils.MilliSecondsBetween(Now(),t)] ) ); end; 比较:
此帖子包含附件: 大小: 507.6K
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/17 22:47:09
20楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
xjia (xjia)
★☆☆☆☆
-
盒子活跃会员
2022/1/17 23:11:41
21楼:
20楼: 那是不是就不是替换的问题,是界面显示的原因?
----------------------------------------------
-
作者:
2022/1/17 23:24:37
22楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 9:15:43
23楼:
那可能就是我说的: 慢不在替换,而是字符串(过大)的处理不一样吧。 毕竟Delphi11早已跨平台了,而Delphi7不用考虑别的平台,也不用管啥unicodestring,widestring。 你用的Richedit,我只能猜基于上面的原因(毕竟隔了20年)VCL组件变化也很大? 毕竟现在内部都用双字节字符串了。 我再试试看……
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/18 10:08:02
24楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 10:13:46
24楼:
60多MB文本,仅仅加载到RichEdit就慢死了啊……95秒。-__- 替换了几分钟没出来。 我把文件缩小到256KB,加载大概1秒,替换8-9秒(包括显示)。 把RichEdit换成Memo后,加载100毫秒,替换200毫秒,替换完的内容放入Memo显示到屏幕上又用了2秒左右。 把加载的内容不放入Memo而是一个StringList,则替换1毫秒完成,替换完的内容放入Memo显示到屏幕上还是2秒左右。这根本就是界面慢啊…… 而且就算这样写,也没快一点点: Memo1.Lines.BeginUpdate; Memo1.Lines.Clear; Memo1.Lines.AddStrings(outList); Memo1.Lines.EndUpdate;
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/18 10:26:53
25楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 10:44:22
26楼:
我的笔记本Thinkpad pad t530 i5-3210m 8G内存,win32 X11编译,执行替换楼主的64兆文本,约200毫秒,delphi x11 文本替换性能没什么问题
----------------------------------------------
-
作者:
2022/1/18 10:46:57
27楼:
测试楼主的64兆文本,我自己写的替换函数319好毫秒,delphi x11自带的函数200毫秒,和楼主说的天差地别
----------------------------------------------
-
作者:
2022/1/18 10:47:56
28楼:
楼主肯定搞错了
----------------------------------------------
-
作者:
hexi (Hexi)
★☆☆☆☆
-
盒子活跃会员
2022/1/18 12:55:55
29楼:
楼主是不是把刷新显示时间也算到stringreplace里面去了
----------------------------------------------
-
作者:
2022/1/18 15:05:33
30楼:
楼主,事情要一件一件的说。 目前未证实的仅是第3点,前面2点已经无需讨论了。 至于D11慢,也许解决不了,请参考第2点。1)D11字符串替换不慢,放到RichEdit界面非常慢。 上面的测试已证明。2)D7界面显示比D11快很多。 推测:D7效率高,很可能是不用考虑下列因素: 字符编码(无法LoadFromFile设置UTF8)。 32/64位。 跨平台。 单字节多字节(仅Ansi)。 但即使比D11快,D7弄到界面显示还是数量级的慢于直接处理字符串。3)D7下Q_ReplaceStr很快,包括界面都快。 楼主写的:Q_ReplaceStr很快呢?64.2MB的文件人家替换完毕到显示完成仅3.3秒!这说明不是界面慢的问题。 我确实重现不了,因为D7下我根本没办法Load进去,RichEdit试图Load个StringList就报EOutOfResouce。 60多MB的文件只能LoadFromFile才能打开,我不熟悉,不知道为什么。 楼主可以贴出代码,让大家看看怎么做到替换完加显示可以3点几秒的。 因为替换是替换,显示是显示,难道不是2步么?逻辑上不会因为你前面用了Q_ReplaceStr,后面显示就能从4秒变成3秒呀。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/18 15:20:55
31楼:
接着上面的,我用了个变通的办法:存临时文件,再加载到RichEdit里面。。。 RichEdit里的数据仅来自和存到文件,其它处理都用内部的StringList。 D7下面,替换60MB多的文本所有'人'变成'★'。 替换方式是循环每行StringReplace(aLine,'人','★',[rfReplaceAll]); 替换用时1.1秒左右。 显示用时3.3秒左右。 LZ参考一下吧,我不太想继续测了,如果一定要用D11显示到界面,我不知道怎么办。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/18 15:36:29
32楼:
个人总结: 1)字符串替换D11和D7其实区别不大。可能效率不是特别高,但是没那么夸张的慢。 2)D11因为要考虑的情况太多,界面用RichEdit展示很大的文本内容效率没有D7高。 3)测试归测试。即便是非界面,也建议不要用TStringList一类来处理文本文件,万一文件很大几十个GB呢。。。在《这个帖子》 里面有一些相关文本读写的讨论。PS:提到了Go效率高,都有人不高兴。。。 怎么展示/编辑那么大的文本,只能结合自己业务逻辑来考虑。对我RichEdit好像只是为了展示有格式的文本会用。工作关系几乎没用到过,只有一个内嵌的帮助用了?找了一下如下图(好像和主题无关):
此帖子包含附件: 大小: 41.2K
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/18 18:45:37
33楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 18:52:39
34楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 18:57:28
35楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 19:04:52
36楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 19:09:56
37楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 19:18:07
38楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
此帖子包含附件: 大小: 306.5K
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 19:25:49
39楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
此帖子包含附件: 大小: 289.7K
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 19:35:44
40楼:
xe11的替换文本函数性能确实没问题,测了替换64兆文本,只花0.2秒,楼主是把文本替换和界面显示混为一谈,稀里糊涂
----------------------------------------------
-
作者:
2022/1/18 19:45:15
41楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 20:41:59
43楼:
//我的笔记本,不到200毫秒 procedure TForm7.SpeedButton1Click(Sender: TObject); var d1: TStopwatch; tmp: string; ts: TStringList; begin ts := TStringList.Create; try ts.LoadFromFile('e:\d1.txt'); d1 := TStopwatch.StartNew; tmp := StringReplace(ts.Text, '人', '★', [rfReplaceAll, rfIgnoreCase]); d1.ElapsedMilliseconds; Caption := IntToStr(d1.ElapsedMilliseconds); ts.Clear; ts.Text := tmp; ts.SaveToFile('e:\d2.txt'); finally ts.Free; end; end;
----------------------------------------------
-
作者:
2022/1/18 20:47:43
44楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 20:51:50
45楼:
Thinkpad pad t530 i5-3210m 8G内存,win32 XE11编译,计算时间174毫秒
此帖子包含附件: 大小: 2,576B
----------------------------------------------
-
作者:
2022/1/18 20:52:30
46楼:
测试60兆文本,174毫秒
----------------------------------------------
-
作者:
2022/1/18 20:54:08
45楼:
楼主试试把 t1:=HPCounter1.ReadInt; //计时开始 放在 Editor.Text:=Q_Replace(S,f,r); //大神用汇编写的替换函数 前面呢? 考察StrReplace的执行时间,最好把计时器的起止紧贴StrReplace函数,否则容易引入额外的干扰因素
----------------------------------------------
-
作者:
2022/1/18 20:55:52
47楼:
替换后的文件是正确的
此帖子包含附件: 大小: 68.7K
----------------------------------------------
-
作者:
2022/1/18 21:02:23
48楼:
看了楼主代码,主要问题是分不清替换和可视化控件赋值显示耗时的问题,计算机基本功的问题
----------------------------------------------
-
作者:
2022/1/18 21:10:16
49楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 21:12:53
50楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 21:20:47
51楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 21:24:16
50楼:
你的问题是RichEdit1跑不动,不是StringReplace不行
----------------------------------------------
-
作者:
2022/1/18 21:34:43
52楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
此帖子包含附件: 大小: 19.4K
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 21:41:28
53楼:
to 50楼: 你现在怀疑的是D11的StringReplace效率差,那就先测StringReplace的执行时间 万一是D11执行 S:= Editor.Text; //文本编辑器 的效率低呢? 那就是另一个话题了 找到问题点,才能知道代码优化的方向
----------------------------------------------
-
作者:
2022/1/18 22:07:39
54楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/18 22:43:50
55楼:
原来LZ是text全部替换的。 加一句话嘛,不就看出来了。 tmp := Q_Replace(S,f,r); 这里计时 Editor.Text:=tmp; 这里计时 vs tmp := StringReplace(ts.Text, '人', '★', [rfReplaceAll, rfIgnoreCase]); 这里计时 Editor.Text:=tmp; 这里计时 不过弄到最后,D11的RichEdit显示60多MB文本,还是不行吧。。。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/19 0:10:39
56楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 8:03:58
57楼:
前面好几个人已经验证了D11的StringReplace效率并不差, 看你的测试代码中,在计时阶段调用了TRichEdit.GetText和TRichEdit.SetText, 万一是这两个在D7和D11下的实现效率有差别呢? D11为了unicode,跨平台,在上面两个函数实现中塞入了太多的东西,也是很有肯能的 楼主可以分别验证一下TRichEdit.GetText, StringReplace, TRichEdit.SetText三个函数在D7和D11下用时
----------------------------------------------
-
作者:
2022/1/19 11:27:17
58楼:
楼主自己的逻辑不清,无数人帮他验证了StringReplace效率不差,他抱着RicheEdit中替换的时间觉得是函数的效率差。 实际上也是RichEdit的效率导致的,RichEdit是Windows系统提供的,Delphi做了个简单的封装。 D7和D11用的RichEdit就不是一个东西。 D7用的是RICHED32.DLL,是微软早期封装的RichEdit非常简陋(可能简单速度就会快)。 D11用的是MSFTEDIT.DLL,更加完善,能处理的东西非常多(处理的东西多,速度会慢一些)。 把UI和函数混在一块来测试函数性能首先逻辑已经混乱了。 把两个不同实现的UI和掺在一块说函数性能不行就是逻辑混乱加逻辑混乱。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2022/1/19 11:30:51
59楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 11:34:29
60楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 11:34:42
60楼:
Q_Replace你是在D7里面用的,RichEdit是旧的 然后和用了新Richedit的D11比,怎么比? 去掉Richedit比才是纯函数性能,你抱着RichEdit的不同实现来测函数? MSFTEDIT是微软实现的4.0的RichEdit。 增加了如下特性: 多级表 自动更正 改进的自动超链接检测 友好名称的超链接 根据书写系统的字体绑定(字符集泛化) 印度支持 垂直文本 支持最新的输入法 语音和手写输入(Windows 文本服务框架) 更标准的热键 你觉得速度应该更快吗? 公平的做法是你在去掉控件,比较函数。或者你在D7上引入新的RichEdit或者在D11上使用旧的RichEdit的核心DLL。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2022/1/19 11:42:34
61楼:
楼主给我的感觉入错行
----------------------------------------------
-
作者:
fdltc (fdltc)
★☆☆☆☆
-
普通会员
2022/1/19 11:55:28
60楼:
武稀松是正解,两个版本的RE内部实现完全不同。 楼主水平还只是停留在拖控件、抄代码阶段,好好努力吧
----------------------------------------------
-
作者:
2022/1/19 12:27:50
62楼:
to 59楼 你连58楼说的东西都没有看懂吧。看懂就不会这么说了。
----------------------------------------------
我是菜鸟,己经搞了十多年了,但是我仍然很菜。
作者:
2022/1/19 12:32:32
63楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
此帖子包含附件: 大小: 365.0K
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 12:36:21
64楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
此帖子包含附件: 大小: 365.0K
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 12:43:52
65楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
此帖子包含附件: 大小: 2.01M
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 14:04:58
66楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
此帖子包含附件: 大小: 2.03M
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 14:42:24
67楼:
LZ真激动啊,我前面写的: tmp := Q_Replace(S,f,r); 这里计时 Editor.Text:=tmp; 这里计时 vs tmp := StringReplace(ts.Text, '人', '★', [rfReplaceAll, rfIgnoreCase]); 这里计时 Editor.Text:=tmp; 这里计时 结果楼主回答: 不同的替换函数替换时Editor.Text:=tmp有区别吗?没任何区别好吧! 确实速度没有区别,但是可以【区分】两个步骤。 去掉界面显示对替换函数的影响,上一句的实际时间不就出来了吗。 由于界面慢,替换函数快,而且是数量级的不同。 那么加入界面的影响后,对测试函数速度是致命的影响。 再直白一点,替换函数的速度用楼主的值。 快的0.03毫秒,自带的慢很多100毫秒。界面显示需要3000毫秒。 本身是 0.03:100 约等于 1:3000。 那么加入界面后: 变成了 3000.003:3100 约等于 1:1。 这个逻辑不需要很专业的编程,了解底层原理等等,静心仔细想想就明白了。 所以大家都在说,减少干扰。 我测试的时候没有整个字符串text替换,是逐行替换的,所以没看出来D11比D7更快。我逐行原因是日常工作要考虑几十GB的文本,习惯了。但是这个并不重要。 我看到最后,没明白LZ的问题到底解决没有…… 问题根源不是字符串替换的效率。即便是数千倍的差异,但是都能秒级别替换完。所以这个也不重要了。 最后似乎并没有解决吧,因为D11的RichEdit无法高效显示太大的字符串。 是这样吧?
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/19 15:15:09
68楼:
const fn = 'f:\test2.txt'; var str, tmp : String; c, i : Integer; begin // {$IFDEF UNICODE} str := System.IOUtils.TFile.ReadAllText(fn); {$ELSE} str := readAllUTF16Text(fn); {$ENDIF} c := GetTickCount; {$IFDEF UNICODE} tmp := StringReplace(str, '人','★',[rfReplaceAll]); {$ELSE} tmp := Q_ReplaceStr(str, '人','★'); //tmp := StringReplace(str, '人','★',[rfReplaceAll]); {$ENDIF} c := GetTickCount - c; Caption := IntToStr(C); end; 同一套代码,去掉你所谓的RichEdit。 在Delphi7里面用你的Q_ReplaceStr,在D11里面用StringReplace。 跑你上面上传的文件,各自测试10次 D7的Q_ReplaceStr的耗时在78-91ms之间 D11的自带StringReplace,在31-46ms之间。 你所谓慢还是慢在D11里面集成微软新的RichEdit,增强的内容特别多,所以慢。实际上单单看字符串替换,D11自带的StringReplace比你所说的Q_ReplaceStr还要快。 结论: Q_ReplaceStr确实比D7自带的StringReplace的要快上几千倍, 但是D11自带的StringReplace比Q_ReplaceStr还要快一倍左右。 D7的RichEdit使用的微软提供的RICHED32.DLL是旧版,功能少,速度快 D11的RichEdit使用的是微软提供的MSFTEDIT.DLL,是4.0以上的版本,功能锁,速度慢。 如果你又想替换快,又想RichEdit加载快。那就用D11,然后使用旧版的RichEdit的DLL。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2022/1/19 15:20:13
68楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 16:49:01
69楼:
我没试 Editor.Text:=tmp,因为当时不知道楼主是这么写的。 但是我试了Editor.Line.AddStrings D7下加载不出来会报错。 D11下速度取决于传入的参数是不是界面的内容。 也试了Editor.Line.LoadFromFile 看我在31楼写的【显示用时3.3秒】就是指它。 替换用时1.1秒左右。 显示用时3.3秒左右。 这几个函数不仅是内部的字符串操作,还要在UI上显示出内容。 很可能不是楼主说的“就赋值的那点时间完全可以忽略不计”…… 【LoadFromFile】大概3.3秒,所以我推测【Text:=】基本耗时相同。 所以我推荐楼主分步骤测试一下。 楼主仔细看看上面的逻辑。 以及实际测试的速度: LZ:“毕竟Q_Replace替换+显示干完64.2MB的文件也就3.3秒” 我:“替换用时1.1秒左右。” 我:“显示用时3.3秒左右。” 综合前面得到的结果:Q_Replace比D7自带replace快1000倍。 结论就非常明显了, 和我在67楼说的一样:加入界面的影响后,对测试函数速度是致命的影响。 为啥我要回复那么多次,是因为我看到楼主最后一贴里面,还是有很多不对的逻辑。很着急啊。。。 比如上面那句替换+显示觉得显示部分赋值不耗时的推测。 比如“你是逐行显示,所以这个UI慢会累加”根本没看我的代码呀…… 实际上代码都贴了,加个计时器自己测试一下,比猜测和怀疑有用得多(楼主甚至让我录屏证明……)哈哈^o^ 希望楼主理解:)
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/19 18:31:16
70楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 18:49:44
71楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 20:30:35
72楼:
好吧楼主你赢了。 我们不对。 我测试的D7原版replace60多MB: 替换用时1.1秒左右。 显示用时3.3秒左右。 肯定是假的。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/19 21:15:58
73楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 21:35:54
74楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 21:49:26
75楼:
楼主,你用错误的测试方法得出了一个错误的结论,赶紧认个错回去优化你的代码吧
----------------------------------------------
-
作者:
2022/1/19 22:10:51
76楼:
D11的StringReplace比D7下的Q_Replace快不仅仅有这个好处,而且是纯Pascal实现的,可以编译到Android,IOS,Linux,MAC等各个平台,比Q_Replace通用不少。 实际上D11的StringReplace和Q_Replace用的同样类似的方式,就是先Pos到所有的匹配字符串,然后算好Result的长度,一次性分配。你自己写的那个之所以非常慢主要就是慢在不停的重新分配Result的内容和长度。 那两个函数都可以看成下面这个基本函数的变形,下面这个函数是在D11上调试的,比内置的StringReplace慢一丝丝,主要是拷贝没有细分情况处理。 function StrReplace(const Source, OldPattern, NewPattern: string): string; const arraySizeStep = 4096; var p, I, patternCount: Integer; oldPatternLen, NewPatternLen, SourceLen: Integer; poses: TArray<Integer>; posesSize: Integer; PDest, pSource, copyLlen: Integer; begin oldPatternLen := Length(OldPattern); NewPatternLen := Length(NewPattern); SourceLen := Length(Source); if (SourceLen < oldPatternLen) or (OldPattern = NewPattern) then begin Result := Source; Exit; end; posesSize := arraySizeStep; SetLength(poses, posesSize); // 把计算好的替换字符串位置填写到poses数组里面 p := 0; patternCount := 0; while true do begin p := Pos(OldPattern, Source, p + oldPatternLen); if (p = 0) then begin Break; end; Inc(patternCount); if posesSize < patternCount then begin Inc(posesSize, arraySizeStep); SetLength(poses, posesSize); end; poses[patternCount - 1] := p; end; // if patternCount > 0 then begin // 计算好返回值的长度,免得一次次重新分配移动,否则这里将成为最耗时的 SetLength(Result, Length(Source) + patternCount * (NewPatternLen - oldPatternLen)); PDest := 1; pSource := 1; // 把Source内容和NewPattern内容拷贝到Result里面。 for I := 0 to patternCount - 1 do begin // 拷贝Source copyLlen := poses[I] - pSource; Move(Source[pSource], Result[PDest], SizeOf(Char) * copyLlen); Inc(pSource, copyLlen); Inc(PDest, copyLlen); // 拷贝NewPattern Move(NewPattern[1], Result[PDest], SizeOf(Char) * NewPatternLen); Inc(PDest, NewPatternLen); //源偏移跳过oldPattern Inc(pSource, oldPatternLen); end; // 拷贝Source最后一部分 copyLlen := SourceLen - pSource; if (copyLlen > 0) then Move(Source[pSource], Result[PDest], SizeOf(Char) * copyLlen); end else Result := Source; end;
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2022/1/19 22:35:41
77楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 22:40:06
78楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/19 23:04:48
79楼:
看了上面些贴子,好佩服武稀松,真的做到诲人不倦,难能可贵。
----------------------------------------------
-
作者:
yookee (yookee)
★☆☆☆☆
-
盒子活跃会员
2022/1/20 1:12:26
80楼:
楼主浪费大家的时间与我无关 但是楼主引出了武大关于新版StringReplace已经变快的结论 嗯,我还得感谢一下楼主
----------------------------------------------
-
作者:
2022/1/20 5:35:18
81楼:
这个问题是由TRichEdit字体的字符集设置错误引起的,可以重现,不是“灵异现象”。 字体为简中字体,如宋体、微软雅黑时一切正常;字体为非简中字体,如Ariel、Segoe UI时显示速度奇慢。
----------------------------------------------
-
作者:
vga (vga)
★☆☆☆☆
-
盒子活跃会员
2022/1/20 11:40:14
83楼:
"Talk is cheap, show me the code! " ^_^
----------------------------------------------
-
作者:
2022/1/20 11:40:19
83楼:
不管是编程,还是干别的什么事情,查问题的时候,尽量把不相关的东西分开,一个一个查,而不是搅合到一起去查。这个是做事情的基本思路。但是,我发现,很多人不具备这种简单的思路。 如果中学物理学得好,这种思路应该是初中就会培养出来的。
----------------------------------------------
-
作者:
2022/1/20 17:12:18
84楼:
我那是吐槽,没想到楼主真的不信。 之前代码删了,又写了一次。 不过楼主说对了,确实不能那么快,因为笔记本要慢一些。。。 procedure TForm1.Button1Click(Sender: TObject); var t: TDateTime; begin t:=now(); RichEdit1.Lines.LoadFromFile('D:\Testddd.txt'); ShowMessage( Format( '%d毫秒,第一次加载。总长度%d。',[MilliSecondsBetween(Now(),t),Length(RichEdit1.Text)]) ); end; procedure TForm1.Button2Click(Sender: TObject); var t: TDateTime; //aTmpS: TMemoryStream; //为什么连流都慢? aTmpS: String; aInList,aOutList: TStringList; i: Integer; begin t:=now(); aTmpS:='D:\Testddd.tmp';//TMemoryStream.Create; aInList:=TStringList.Create; aOutList:=TStringList.Create; RichEdit1.Lines.SaveToFile(aTmpS); aInList.LoadFromFile(aTmpS); for i:=0 to aInList.Count -1 do begin aOutList.Add(StringReplace(aInList[i],'人','★',[rfReplaceAll])); end; ShowMessage( Format( '%d毫秒,替换字符串。',[MilliSecondsBetween(Now(),t)] ) ); t:=now(); //aTmpS.Clear; aOutList.SaveToFile(aTmpS); RichEdit1.Lines.LoadFromFile(aTmpS); FreeAndNil(aOutList); FreeAndNil(aInList); //FreeAndNil(aTmpS); ShowMessage( Format( '%d毫秒,替换后加载。',[MilliSecondsBetween(Now(),t)] ) ); end; 也是年末闲得……顺便祝大家虎年大吉 :)
此帖子包含附件: 大小: 91.7K
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/20 17:16:58
85楼:
parhelia分析的有道理。 pcplayer说的有道理。
----------------------------------------------
-
作者:
2022/1/21 0:46:35
86楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
此帖子包含附件: 大小: 1.14M
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/21 0:51:01
87楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/21 1:16:06
88楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/21 16:21:51
89楼:
字体和字符串替换有啥关系?完全就是两码事,非要扯到一起来查,当然查不出来。 一个人又吃了耗子药,又打了篮球。非要说打篮球会致命。
----------------------------------------------
-
作者:
2022/1/21 20:54:10
90楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/21 21:17:53
91楼:
对于替换我没有任何观点。。。 我测出来是怎样的,就写了出来而已。 我的观点是实验要减少干扰,能细分就不要混在一起。 前面你11秒多才替换完。 可能是因为字体原因,存盘慢了。 纯猜的…… 理由如下,耗时的代码只有这几句。其它的时间可以忽略。 //UI组件可能受干扰因素较多。 RichEdit1.Lines.SaveToFile(aTmpS); //时间相对固定 aInList.LoadFromFile(aTmpS); //时间相对固定 for i:=0 to aInList.Count -1 do begin aOutList.Add(StringReplace(aInList[i],'人','★',[rfReplaceAll])); end; PS:我的笔记本是10870H,不快。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/21 21:20:50
92楼:
顺便多说一句:既然分步骤太多,不如打个日志,省的弹窗了。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/1/21 21:41:32
93楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
此帖子包含附件: 大小: 221.5K
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/21 22:09:08
94楼:
没想到这个话题还没结束 :) to 楼主, 2+3<1+5大家都同意,但是推理出来2<1就不是所有人都认同了。 如果你知道我在说什么,就不要回复了 上面好几个帖子都在告诉你你的方法不对,包括你不赞同的pcplayer,简直是高屋建瓴,并且告诉你了“相对更加正确”的方法,你一直在纠缠你测试来的结果就是这样。测试结果是没错,但是结论错了 遁了~~~
----------------------------------------------
-
作者:
2022/1/21 22:36:35
95楼:
大家不要说了, 人家不靠这个吃饭, 人家开心就好, 我们这些老coder又何必惹人家不开心呢? 我希望我这个回复是这个帖子的最后一个回复.
----------------------------------------------
UniKeeper V10.40 -- 您最贴心的个人数据管理助手
作者:
2022/1/21 23:27:06
96楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/22 1:57:21
97楼:
StringReplace效率大幅提高是最近几年的一个官方改进,是有官方宣布的,李维都专门讲过这个问题,你们都不知道吗?算是最近几个版本的小小亮点之一。
----------------------------------------------
只有偏执狂才能生存!
作者:
2022/1/22 16:52:05
98楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/22 20:02:00
99楼:
下面的代码就是按楼主的方法直接替换RichEdit1里面的文本了,用一台10年老电脑(E3 1230V2)来测试,耗时为6.4秒,这个结果应该和使用Q_ReplaceStr差不多了。Delphi版本: 10.3.3 procedure TForm1.ButtonModClick(Sender: TObject); var DeltaTime: TDateTime; begin DeltaTime := Now(); //耗时为6.4秒 //62M文本数据 RichEdit1.Text := StringReplace(RichEdit1.Text, '人', '★', [rfReplaceAll, rfIgnoreCase]); DeltaTime := Now() - DeltaTime; EditMod.Text := FormatDateTime('s:zzz', DeltaTime); end;
----------------------------------------------
-
作者:
2022/1/22 20:41:59
100楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/1/29 23:50:06
101楼:
原因: 虽然用了AnsiString实现了功能,但Delphi11的界面控件是Unicode的,所以从界面里读数据要经过一次转换,写回界面又经过一次转换。 建议: 1、直接改汇编代码使其支持Unicode 2、不要在界面里直接替换数据,替换好了再加载。 3、超大的数据也不要在界面里一次加载,就算加载了也没有屏幕能显示下,影响效率。
----------------------------------------------
-
作者:
2022/2/2 18:56:05
102楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
发布广告,禁用帐号!
作者:
2022/2/7 8:54:45
103楼:
StringReplace在D11比D7肯定要快很多。
----------------------------------------------
-
作者:
2022/2/9 9:59:58
104楼:
StringReplace 里面用到move,pos等几个函数,从Delphi2005开始就使用了fastcode提供的版本,后续的新版集成了很多fastcode的函数,和fastmm内存管理器的加持,我也觉得新版本的性能更好。
----------------------------------------------
Delphi4Linux Delphi三层/FireDAC 技术群:734515869 http://www.cnblogs.com/rtcmw
作者:
2022/2/16 17:20:09
105楼:
D7 编译器的环境不一样,结果也不一样 FastMM MidasSpeedFix VCLFixPack DelphiSpeedUp
----------------------------------------------
-