如何快速 统计 一个文本文件中 某个指定字符 出现的个数 ?

chinawcs 2008-11-21 09:08:44
比如 统计字符 回车符 或者 换行符

主要是算法 速度要快

谢谢
...全文
1055 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
僵哥 2008-11-21
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 ERR0RC0DE 的回复:]
不然针对一个XXXMB的文件,只统计某字符的计数,好像太无聊了。要我就这么干
[/Quote]
估计是要统计有多少“行”。
ERR0RC0DE 2008-11-21
  • 打赏
  • 举报
回复
不然针对一个XXXMB的文件,只统计某字符的计数,好像太无聊了。要我就这么干
ERR0RC0DE 2008-11-21
  • 打赏
  • 举报
回复
既然是XXXMB,你取个巧,取1/10,如10M-50M,一次性加到内存,得到计数X,然后Result=X*10,保证用户不会说什么,呵呵
僵哥 2008-11-21
  • 打赏
  • 举报
回复
用分段读取,进行统计。
chinawcs 2008-11-21
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 zhaoxiaohao 的回复:]
var
a,temp:string;
l:integer;
begin
temp:=stringreplace(a,#13,'',[rfreplaceall]);
l:=length(a)-length(temp);
showmessage(inttostr(l));
end;
[/Quote]

注意文本文件很大 XXXMB 一般 不可一次读入内存的
chinawcs 2008-11-21
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 unsigned 的回复:]
是某一个还是某几个?有汉字等多字节字符吗?
[/Quote]

判断某一个字符 比如回车符
zhaoxiaohao 2008-11-21
  • 打赏
  • 举报
回复
var
a,temp:string;
l:integer;
begin
temp:=stringreplace(a,#13,'',[rfreplaceall]);
l:=length(a)-length(temp);
showmessage(inttostr(l));
end;
寻梦928 2008-11-21
  • 打赏
  • 举报
回复
没什么快速的方法加载到流里,逐个判断累计!
僵哥 2008-11-21
  • 打赏
  • 举报
回复
是某一个还是某几个?有汉字等多字节字符吗?
lake_cx 2008-11-21
  • 打赏
  • 举报
回复
用ReadBuffer就成了
xiedewei 2008-11-21
  • 打赏
  • 举报
回复
多谢僵哥提醒,修改一下:
procedure TForm1.Button1Click(Sender: TObject);
var
T: Cardinal;
S: string;
I, J, M, N, Count: Integer;
Stream: TFileStream;
const
SSize: Integer = $100000; //1MB
begin
T := GetTickCount;
Count := 0;
SetString(S, nil, SSize);
Stream := TFileStream.Create('D:\恋爱假期CD1.rmvb', fmOpenRead);
try
M := Stream.Size div SSize;
for I := 0 to M do
begin
N := Stream.Read(Pointer(S)^, SSize);
for J := 1 to N do
if S[J] = #10 then Inc(Count);
end;
finally
Stream.Free;
end;
ShowMessage(IntToStr(GetTickCount - T)+' '+IntToStr(Count));
end;
僵哥 2008-11-21
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 cranley 的回复:]
要精确统计,只能遍历了。

如果只是两三个字符的串统计,用一个指针一路跑过去

如果是一个大字符串统计,考虑一下使用KMP算法

如果文件太大,分段缓存。
[/Quote]
他只统计一个字符,只需要遍历就可以,分段处理。
cranley 2008-11-21
  • 打赏
  • 举报
回复
要精确统计,只能遍历了。

如果只是两三个字符的串统计,用一个指针一路跑过去

如果是一个大字符串统计,考虑一下使用KMP算法

如果文件太大,分段缓存。
僵哥 2008-11-21
  • 打赏
  • 举报
回复
16楼的注意一下,TFileStream.Read需要对返回值进行处理,养成良好的习惯。
xiedewei 2008-11-21
  • 打赏
  • 举报
回复
手头没有XXXMB的txt,找了一个266MB的rmvb测试了一下。
9.397s得到结果,应该可以接受吧。
效率主要由硬盘性能决定。
适当调整SSize。
procedure TForm1.Button1Click(Sender: TObject);
var
T: Cardinal;
S: string;
I, J, M, N, Count: Integer;
Stream: TFileStream;
const
SSize: Integer = $100000; //1MB
begin
T := GetTickCount;
Count := 0;
SetString(S, nil, SSize);
Stream := TFileStream.Create('D:\恋爱假期CD1.rmvb', fmOpenRead);
try
M := Stream.Size div SSize;
N := SSize;
for I := 0 to M do
begin
Stream.Position := SSize * I;
Stream.Read(Pointer(S)^, SSize);
if I = M then N := Stream.Size mod SSize;
for J := 1 to N do
if S[J] = '+' then Inc(Count);
end;
finally
Stream.Free;
end;
ShowMessage(IntToStr(GetTickCount - T)+' '+IntToStr(Count));
end;
僵哥 2008-11-21
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 chinawcs 的回复:]
判断 #10

谢谢僵哥

我前两天还开了2个帖子 有时间给回回 分都给你了!
http://topic.csdn.net/u/20081120/12/78aac1ee-5081-4fd6-8c8e-02e3562e545a.html
http://topic.csdn.net/u/20081120/12/78aac1ee-5081-4fd6-8c8e-02e3562e545a.html
http://topic.csdn.net/u/20081119/15/1050015c-6743-4a5e-86ab-65ea97fd2d4e.html
[/Quote]
抱歉,不是所有问题我都能回复得了的。从来就没做过报表。对那些第三方的控件不熟悉。
僵哥 2008-11-21
  • 打赏
  • 举报
回复
文件只有几百兆的话,那么可以使用任何文件IO操作来一段段读取,进行统计。
xiedewei 2008-11-21
  • 打赏
  • 举报
回复
是否有 跟 有多少 不一样的 你要哪样?
chinawcs 2008-11-21
  • 打赏
  • 举报
回复
判断 #10

谢谢僵哥

我前两天还开了2个帖子 有时间给回回 分都给你了!
http://topic.csdn.net/u/20081120/12/78aac1ee-5081-4fd6-8c8e-02e3562e545a.html
http://topic.csdn.net/u/20081120/12/78aac1ee-5081-4fd6-8c8e-02e3562e545a.html
http://topic.csdn.net/u/20081119/15/1050015c-6743-4a5e-86ab-65ea97fd2d4e.html
僵哥 2008-11-21
  • 打赏
  • 举报
回复
到底是要判断#13#10还是要判断#10?
加载更多回复(1)

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧