怎么用文件流或者内存流一行一行的读取文本文件

taoran12 2010-10-11 06:36:29
如题,请教!
...全文
544 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
taoran12 2010-10-17
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 wxieyang 的回复:]
这个问题,还是要看你如何处理数据
如果数据时一边读一边处理,并且处理完的数据不会回头再处理,那么用内存映射还是比较方便的。
但是,如果处理时随机的,那用内存映射一段一段处理就麻烦了,比如100M的数据,我映射了1M,处理完了,然后又映射了1M,当后面得处理完了,发现还需要处理前面1M的数据,那内存映射就比较麻烦了
[/Quote]
所用的数据都只处理一遍,并且还是多线程处理,100Mb的数据每个线程各处理50MB,这样可以吗?
taoran12 2010-10-16
  • 打赏
  • 举报
回复
问题是我想用流来提高读取速度,但程序也要求对每一行的数据进行分割,所以我也得知道每一行的数据。7楼说的好像是那么回事,能写段代码我看看吗?
taoran12 2010-10-16
  • 打赏
  • 举报
回复
问题是我想用流来提高读取速度,但程序也要求对每一行的数据进行分割,所以我也得知道每一行的数据。7楼说的好像是那么回事,能写段代码我看看吗?
wxieyang 2010-10-16
  • 打赏
  • 举报
回复
这个问题,还是要看你如何处理数据
如果数据时一边读一边处理,并且处理完的数据不会回头再处理,那么用内存映射还是比较方便的。
但是,如果处理时随机的,那用内存映射一段一段处理就麻烦了,比如100M的数据,我映射了1M,处理完了,然后又映射了1M,当后面得处理完了,发现还需要处理前面1M的数据,那内存映射就比较麻烦了
wooden954 2010-10-15
  • 打赏
  • 举报
回复
读取一行,与5楼的函数一样,应该用Readln
楼上各位讨论的速度问题与本函数没有什么太大关系,但如果用StringList的话,LoadFromFile或LoadFromStream会把全部文件读到内存中,速度太慢,
读取流的话,应该在需要的时候读取需要的行数,
自己控制读取进度,这样速度上就快多了.
这种办法读取上百兆文件的时候(阅读或分析)时,会显得速度快得多.
Steven_WU 2010-10-15
  • 打赏
  • 举报
回复
进来学习了
kye_jufei 2010-10-13
  • 打赏
  • 举报
回复
TStringList有LoadFromStream...
t1122 2010-10-13
  • 打赏
  • 举报
回复
才发现,原来8年前水平很低啊!仅作参考!仅做参考!自己改啊
t1122 2010-10-13
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 wxieyang 的回复:]
大文件,你可以用内存映射文件的方式,一次只打开一部分处理。
采用内存映射的方式,因为可以看成是内存指针(或者说是PChar),所以,你只需要扫描到#13#10两个字符,就说明是读了一行
自己做个从内存指针中一次读一行的函数就是了
[/Quote]

没有必要吧?费两遍事?
写一个我的小程序,读的文件虽然没有100m但是10+m还是有的,速度还行。
procedure TForm1.BLClick(Sender: TObject);
var
f:textfile;
s,q:string;
i,j:integer;
begin
s:='C:\Documents and Settings\Administrator\桌面\对比可用额度\';
q:=s;
self.M_A.Lines.Clear;
self.M_B.Lines.Clear;
self.M_A.Lines.BeginUpdate;
self.M_B.Lines.BeginUpdate;
if not fileexists(s+'a.txt') then
showmessage('a.txt不存在!');
if not fileexists(s+'b.txt') then
showmessage('b.txt不存在!');

//读入a.txt,
i:=0;
if fileexists(q+'a.txt') then
begin
assignfile(f,s+'a.txt');
reset(f);
while not eof(f) do
begin
readln(f,s);
//如果是带“.”的需要 s:=stringreplace(s,'.00','',[rfReplaceAll]);
str[i]:=s;
i:=i+1;
//self.M_A.Lines.Add(s);
end;
closefile(f);
end;
// QuickSort(str,0,i-1);
for j:=0 to i-1 do
begin
self.M_A.Lines.Add(str[j]);
end;



//读入b.txt,
if fileexists(q+'b.txt') then
begin
assignfile(f,q+'b.txt');
reset(f);
for i:=1 to 7 do
readln(f,s);
while not eof(f) do
begin
readln(f,s);
// self.M_B.Lines.Add(s);
if (copy(s,1,4)=' ') then
begin
s:=copy(s,16,5)+' '+ floattostr(strtofloat(trim(copy(s,48,15))));
self.M_B.Lines.Add(s);
end;
end;
closefile(f);
end;
self.M_A.Lines.EndUpdate;
self.M_B.Lines.EndUpdate;

end;


注意一下:一条一条读取数据肯定是你有要处理的东西,好比我这个就是需要读取其中一部分。处理的时候经常会用到排序,delphi自带的排序QuickSort有严重bug,你需要找到那个文件改一下,加上边界处理,还有7以内的排序速度会很慢,如果经常用就要自己优化一下。这段程序有点旧,8年前的吧,好像是,嘎嘎,别问我,还要现回忆……网上找吧,很多的。
wxieyang 2010-10-12
  • 打赏
  • 举报
回复
大文件,你可以用内存映射文件的方式,一次只打开一部分处理。
采用内存映射的方式,因为可以看成是内存指针(或者说是PChar),所以,你只需要扫描到#13#10两个字符,就说明是读了一行
自己做个从内存指针中一次读一行的函数就是了
likeyrain 2010-10-12
  • 打赏
  • 举报
回复
以上两种方法都用过,方法可行,不过至于大文件,100M的,就没试过,估计要一定的时间,
oloveuxyz 2010-10-12
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 wxieyang 的回复:]
大文件,你可以用内存映射文件的方式,一次只打开一部分处理。
采用内存映射的方式,因为可以看成是内存指针(或者说是PChar),所以,你只需要扫描到#13#10两个字符,就说明是读了一行
自己做个从内存指针中一次读一行的函数就是了
[/Quote]

赞成!
taxi 2010-10-11
  • 打赏
  • 举报
回复
还可以用TextFile变量读文本文件,也可以一行一行的读.
var
f: TextFile;
s: string;
begin
AssignFile(f, 'c:\temp.txt');
Reset(f);
while not Eof(f) do
begin
Readln(f, s);
ShowMessage(s);
end;
CloseFile(f);
end;
haitao 2010-10-11
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 taoran12 的回复:]
引用 1 楼 taxi 的回复:
用TStringList挺简单的嘛,干嘛用流读。
TStringList有LoadFromStream方法。

用TstringList读取大文件的时候会不会太慢啊,比喻说100MB以上的?
[/Quote]

看你的需求了,如果可以读一行处理一行的,TstringList读取大文件的模式当然有点冤枉
taoran12 2010-10-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 taxi 的回复:]
用TStringList挺简单的嘛,干嘛用流读。
TStringList有LoadFromStream方法。
[/Quote]
用TstringList读取大文件的时候会不会太慢啊,比喻说100MB以上的?
SQLDebug_Fan 2010-10-11
  • 打赏
  • 举报
回复
纠正一个概念,流是没有行的概念。
taxi 2010-10-11
  • 打赏
  • 举报
回复
用TStringList挺简单的嘛,干嘛用流读。
TStringList有LoadFromStream方法。

5,388

社区成员

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

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