在本版的第一帖============文本文件操作问题~~~

fishmans 2005-10-26 03:32:11
有一个文本文件,2W行,每行65个字节
本人想查询指定内容后删除内容所在的行,
除了把文件整个读进来操作后再写回外还有别的方法吗??



如:
123123123...
dfsasdfwer...
#$%^&*())...

我要找dfs,然后把dfs所在行删除
结果就是
123123123...
#$%^&*())...
...全文
242 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
zsp0010 2005-11-02
  • 打赏
  • 举报
回复
MARK
fishmans 2005-10-28
  • 打赏
  • 举报
回复
谢谢各位的技术支持~~
严重感谢hellolongbin(一个人[终不似 少年游]) 的大力帮助~~~

感觉分太少不好分,加到100先~

结帐
hellolongbin 2005-10-28
  • 打赏
  • 举报
回复
String类型最大可以到2G,你不必担心
hellolongbin 2005-10-28
  • 打赏
  • 举报
回复
StringList.Text是一个String类型,内容是包括回车换行在内的文件所有内容,你完全可以用操作字符串的方法对它操作,比如,找到123123123的位置,然后去掉中间65个字符(包括换行),字符串的操作你总该会吧?

如果你觉得还是不够快或者不够方便,不妨试试其他人的方法

2W行真的不算大的文件,如果文件超过百万行或者大于几十M,可以考虑用AssignFile或其他内存操作方法,象你的问题,就算直接循环也不会超过5秒。再试试吧,有问题继续回帖
fishmans 2005-10-27
  • 打赏
  • 举报
回复
eastnofail(Char *) :
2W条也就1M多,而且数据量也不会再增加很多。
但是内存映射这个东东没做过,不知道如何下手,能给个例子吗?

hellolongbin(一个人[终不似 少年游]) :
因为一条记录中可能会有换行,如果用Tstringlist读会把一条记录隔断,那么这就不合适了。
{============================================================}
我原来想用Tfilestream来做,但是不知道怎么一次把65个字节清除.
hellolongbin 2005-10-27
  • 打赏
  • 举报
回复
hellolongbin(一个人[终不似 少年游]) :
这样读出来每个Tstringlist.string[index]都是65个字节吗?
----------------------------------------------
Tstringlist.string[index]的内容是由你的文本内容决定的
eastnofail 2005-10-27
  • 打赏
  • 举报
回复
老实说,用TStringList或者String都不是正宗的解法,虽然他们一样可以做到,这种对大文件的操作最好的做法是 xixuemao(动感超淫) 说的方法,把文件所在的磁盘映射为虚拟内存页面,然后你删除也好插入也好,就跟操作内存完全一样.

当然,这种做法更复杂一些,使用TStringList会更简单一些,不过,如果你的数据量有可能进一步增大,比如,可能会超过几百M,那么你的内存会爆掉
fishmans 2005-10-27
  • 打赏
  • 举报
回复
hellolongbin(一个人[终不似 少年游]) :
这样读出来每个Tstringlist.string[index]都是65个字节吗?
hellolongbin 2005-10-27
  • 打赏
  • 举报
回复
nnd,基础错误,忘了free了 BS自己一个

procedure TForm1.Button1Click(Sender: TObject);
var st:TStringList;
begin
st:=TStringList.Create;
st.LoadFromFile('D:\1.txt');
st.Text:=AnsiReplaceStr(st.Text,'hehe'+#13#10+' test','');//允许换行
st.SaveToFile('D:\2.txt');
st.Free;
ShowMessage('ok');
end;
hellolongbin 2005-10-27
  • 打赏
  • 举报
回复
读取删除和都不是问题,关键是看效率

我觉得2W行应该不算太大,用StringList速度上也是说的过去的,我试着做了一个2W多行的文本跑了一下,用了不到5秒就ok了,下面试我的代码

procedure TForm1.Button1Click(Sender: TObject);
var st:TStringList;
begin
st:=TStringList.Create;
st.LoadFromFile('D:\1.txt');
st.Text:=AnsiReplaceStr(st.Text,'hehe'+#13#10+' test','');//允许换行
st.SaveToFile('D:\2.txt');
ShowMessage('ok');
end;
fishmans 2005-10-27
  • 打赏
  • 举报
回复
hellolongbin(一个人[终不似 少年游]) :

但我比较的只是一条记录的前面几个字节,不会去全匹配的。

而且如果说一条记录是这样的:
123123123....
..dfwewererer//(共65字节)
而Tstringlist读成两行的话,那肯定是不行的啊
hellolongbin 2005-10-27
  • 打赏
  • 举报
回复
因为一条记录中可能会有换行,如果用Tstringlist读会把一条记录隔断,那么这就不合适了。
----------------
你没看懂我举的例子
fishmans 2005-10-26
  • 打赏
  • 举报
回复
=============重新整理一下问题==========================

有一个文本文件,2W条记录,每条记录65个字节,这65个字节中可能会有换行符什么的,所以可能一条记录不在一行,用行读应该是不行的。

然后我要与其他的操作去对比这个文件,比如说跟一个数据库中的数据比较,数据库中存在与文本文件中的数据一样记录的就把文本文件中的这条记录删除同时把数据库中的记录也删除。

为了数据一致性,最好能实时对这个文件做处理,所以我才不想把整个文件读进来做操作再写回去。
还有一点就是,这个文件可能会用在linux系统下。

====================问题就是这样,有不足,后面再补充==========================
=============================分不够可以再加===================================
sdzeng 2005-10-26
  • 打赏
  • 举报
回复
procedure TForm1.Button1Click(Sender: TObject);
var
F1,F2 : TextFile;
s : string;
begin
AssignFile(F1,'E:\a.txt');
Reset(F1);
AssignFile(F2,'E:\a.bak');
Rewrite(F2);

while not Eof(F1) do
begin
Readln(F1, s);
if AnsiPos('dfs',s)=0 then
begin
Writeln(F2,s);
end;
end;
CloseFile(F1);
Erase(F1);
CloseFile(F2);
RenameFile('E:\a.bak','E:\a.txt');

end;
g961681 2005-10-26
  • 打赏
  • 举报
回复
没做过,不过2w行数据,是个不小的东西了,不能用tstringlist处理的。
我的想法是用tfilestream,以流的方式一行一行的读取数据,再选择性的删除。
没实现过,当我瞎讲的。其实是想近来等答案~~~~~~~~~

********************************************************************
*TryMyBestToKnowSomethingAboutEverythingAndEverythingAboutSomething!
********************************************************************
fishmans 2005-10-26
  • 打赏
  • 举报
回复
summersky204608() :
这个TstringList.loadfromfile是以什么为分隔的?
因为每条记录是65个字节,可能其中有换行符什么的,所以一条记录有可能不是一行,这样得到的行数可能不对吧?

xixuemao(动感超淫) :
内存映射怎么做?
xixuemao 2005-10-26
  • 打赏
  • 举报
回复
内存映射
summersky204608 2005-10-26
  • 打赏
  • 举报
回复
用TStringList后台处理,还是比较快的!
procedure TForm1.Button1Click(Sender: TObject);
var i:integer;b,d:TstringList;l:string;
begin
if OpenDialog1.Execute then
begin
b:=TstringList.Create ;
d:=TstringList.Create ;
d.Clear;
b.LoadFromFile(OpenDialog1.FileName);//打开相应的文件逐行读取;
for i:=0 to b.Count-1 do
begin
l:=b.Strings[i];
if pos('123',l)>0 then //查找到含指定字符串的一行;
l:=''; //清空;
if l<>'' then //字符串不为空则保存,为空继续执行
d.Add(l);
end;
end;
d.SaveToFile(OpenDialog1.FileName); //读完后保存新生成的文件,若不想覆盖
d.Free; 原文件,可以用OpenDialog1.FileName
b.Free; 直接加个后缀,这样就可以不破坏原文件
ShowMessage('Ok'); 而得到一个新的文件!
end;



rlqiang 2005-10-26
  • 打赏
  • 举报
回复
好问题,不过不会。我想string可以读2G的。不用担心吧。

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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