同样的问题见帖子http://www.csdn.net/expert/topic/1043/1043077.xml?temp=.7008936
问题一
我想将一个很大的文本文件的内容经过一定的文本替换处理后读入一个字符型变量txtall中,并将经处理后的文本内容显示到RichEdit1中.我的代码如下:
RichEdit1.Lines.LoadFromFile(OpenDialog1.FileName);
RichEdit1.Text:=StringReplace(RichEdit1.Text,'-','',[rfReplaceAll]);//, rfIgnoreCase]);
txtall:=RichEdit1.Text;
我发现执行第一行代码用的时间很短,但是第二行代码执行时间非常长.
请问如何改进代码才能使用时最短.顺便说明,以上提到的文本文件的行数在10万行以上,文本中有大量的字符'-'要删除.问题二
Delphi中有没有替换某个字符串中从某个位置开始的长度为N的子串为另一字符串的函数?在VB中可以用Mid$函数,那么在DELPHI中用哪个函数呢?
Private Sub Command1_Click()
  Dim str As String
  str = "abcdefghijklm"
  Mid$(str, 4, 5) = "XYZAB" ' 将str的第四个字符开始的5个字符defg替换为XYZAB
  MsgBox str
End Sub我用VB的Replace函数载入一个1400多行的文本文件(含有大量的'-'号,大约占44%),并将其中的'-'替换为'',最后显示处理后的结果显示在RichEdit中只需要0.12秒,用我前面的Delphi代码竟然用了3.79妙!同样有大量的替换操作,为何VB快这么多?当处理5万多行的文本文件时,VB用时22秒,用Delphi算了五分钟都毫无反映?高手们,救命啊,我刚开始学Delphi,给我一点对DELPHI的信心吧!

解决方案 »

  1.   

    1.StringReplace的速度确实慢!要不这样吧,用VC写个DLL,把String转为PChar在该DLL中处理后返回!MFC中的Replace确实要比StringReplace快几倍!如上说,和String的内存分配规则有关!但如果只是要消除那种毫无反应的现象,在线程内操作即可!2.咳,教了你学习的方法,你还是不会,看来鱼比渔好啊!str:="abcdefghijklm";
    delete(str,4,5);
    s:='XYZAB';
    insert(str,s,4);
      

  2.   

    还学什么delphi啊,工作都很难找了
      

  3.   

    兄弟,我的DELPHI代码替代了85000行只用了16秒!!!!
    看我的代码!!!!!!!用好DELPHI吧,大部分比VB快(可能有不快的方面)。
    我是把“-“ 替换为“@”了。
    procedure TForm1.Button1Click(Sender: TObject);
    var
    s:string;
    i:integer;
    begin
    memo1.Visible :=false;
    memo2.Visible :=false;
    memo1.Lines.LoadFromFile('d:\shonline.txt');
    for i:=0 to  memo1.Lines.Count do
      begin
        s:=StringReplace(Memo1.Lines.Strings[i]  ,'-','@',[rfReplaceAll]);
        Memo2.Lines.Add(s);
      end;
    memo1.Visible :=true;
    memo2.Visible :=true;
    end;
      

  4.   

    大家可以试试,我的文本共 80414 行,每一行都有“-”,我用我的笔记本(PIII800,128M)做的测试,算上加载文本文件共用时: 16.9秒。
      

  5.   

    我写了一个Relpace的程序,在大批量replace的时候比delphi的函数效率高多了!Type
      PBufferLink = ^TBufferLink;
      TBufferLink = Record
        Buffer:PChar;
        BufSize:integer;
        Prev:PBufferLink;
      end;function BigReplace(Source:String;OldStr, NewStr:string;BufferSize:integer=64000):string;
    Var
      CurLink,PrevLink:PBufferLink;
      CurBufPos:integer;
      FoundPos:integer;
      OldStrLen,NewStrLen:integer;  procedure NewBuf;
      begin
        GetMem(CurLink,SizeOf(TBufferLink));
        With CurLink^ do
        begin
          GetMem(Buffer,BufferSize+1);
          BufSize := BufferSize;
          Buffer[BufferSize]:=#0;
          Prev := PrevLink;
          PrevLink:=CurLink;
        end;
      end;  procedure FillBuf(const s:string;Size:integer);
      var
        P:PChar;
      begin
        while true do
        begin
          if CurBufPos+Size>BufferSize then
          begin
            P:=CurLink^.Buffer+CurBufPos;
            Move(PChar(S)^,P^,BufferSize - CurBufPos);
            Dec(Size,BufferSize - CurBufPos);
            CurBufPos:=0;        NewBuf;
          end else
          begin
            P:=CurLink^.Buffer+CurBufPos;
            Move(PChar(S)^,P^,Size);
            inc(CurBufPos,Size);
            Break;
          end;
        end;
      end;
    begin
      CurLink:=Nil;
      PrevLink:=Nil;
      CurBufPos:=0;
      OldStrLen:=Length(OldStr);
      NewStrLen:=Length(NewStr);
      Try
        NewBuf;    While True do
        begin
          FoundPos:= Pos(OldStr,Source);
          if FoundPos>0 then
          begin
            FillBuf(Source,FoundPos -1);
            FillBuf(NewStr,NewStrLen);
            Delete(Source,1,FoundPos + OldStrLen -1);
          end else
          begin
            FillBuf(Source,Length(Source));
            Break;
          end;
        end;
      finally
        if CurBufPos<BufferSize then CurLink.Buffer[CurBufPos]:=#0;
        Result:='';
        while CurLink<>Nil do
        begin
          Result:=Result + String(CurLink.Buffer);
          FreeMem(CurLink^.Buffer);
          PrevLink:=CurLink.Prev;
          FreeMem(CurLink);
          CurLink:=PrevLink;
        end;
      end;
    end;
      

  6.   

    呵呵,我比较弱,只能回答你第二个问题:可以用AnsiReplaceStr函数。
    AnsiReplaceStr(const AText, AFromText, AToText: string): string;
    AText为那个文本,AFromText为要查找的文本,AToText为要替换成的文本。唉!我太弱了。
    收藏
      

  7.   

    to :  keyz(keyz)
    你的函数我试了,好象没有DELPHI自己带的快。
    最好多几次测试,取个平匀值。
    我的文本共 80414 行,每一行都有“-”,我用我的笔记本(PIII800,128M)做的测试,用DLPHI自己的,共用时: 16.9秒,而你的函数用了:20.2秒。
    (别生气,我没别的意思,只是技术讨论)我把程序源程序放在网上,大家可以试一下,包括测试文本。http://www.cnborn.com/str.zip (是DELPHI6下调试的)
    欢迎下载测试一下。
      

  8.   

    改进了程序,超快!呵呵。在我的机器上测试你的文件大概1秒多。Type
      PBufferLink = ^TBufferLink;
      TBufferLink = Record
        Buffer:PChar;
        BufSize:integer;
        Prev:PBufferLink;
      end;function BigReplace(Source:String;OldStr, NewStr:string;BufferSize:integer=64000):string;
    Var
      CurLink,PrevLink:PBufferLink;
      CurBufPos:integer;
      FoundPos:integer;
      OldStrLen,NewStrLen:integer;
      POldStr,PNewStr,PSource:PChar;  procedure NewBuf;
      begin
        GetMem(CurLink,SizeOf(TBufferLink));
        With CurLink^ do
        begin
          GetMem(Buffer,BufferSize+1);
          BufSize := BufferSize;
          Buffer[BufferSize]:=#0;
          Prev := PrevLink;
          PrevLink:=CurLink;
        end;
      end;  procedure FillBuf(s:pchar;Size:integer);
      var
        P:PChar;
      begin
        if Size<=0 then Exit;
        while true do
        begin
          if CurBufPos+Size>BufferSize then
          begin
            P:=CurLink^.Buffer+CurBufPos;
            Move(S^,P^,BufferSize - CurBufPos);
            Dec(Size,BufferSize - CurBufPos);
            S:=S+BufferSize - CurBufPos;
            CurBufPos:=0;        NewBuf;
          end else
          begin
            P:=CurLink^.Buffer+CurBufPos;
            Move(S^,P^,Size);
            inc(CurBufPos,Size);
            Break;
          end;
        end;
      end;  Function MyPos(Str,SubStr:PChar):integer;
      var
        I,L:integer;
      begin
        Result:=0;
        I:=0;
        L:=Length(SubStr);
        While True do
        begin
          if Str[I]=#0 then Exit else
          if SubStr[0]=Str[I] then
          begin
            if CompareString(LOCALE_USER_DEFAULT, 0, Str+I,L, SubStr, L) = 2 then
            begin
              Result:= I+1;
              Exit;
            end;
          end;
          Inc(I);
        end;
      end;begin
      CurLink:=Nil;
      PrevLink:=Nil;
      CurBufPos:=0;
      OldStrLen:=Length(OldStr);
      NewStrLen:=Length(NewStr);
      PSource:=PChar(Source);
      POldStr:=PChar(OldStr);
      PNewStr:=PChar(NewStr);
      Try
        NewBuf;    While True do
        begin
          FoundPos:=myPos(PSource,POldStr);
          if FoundPos>0 then
          begin
            FillBuf(PSource,FoundPos -1);
            FillBuf(PNewStr,NewStrLen);
            PSource:=PSource+FoundPos+OldStrLen-1;
          end else
          begin
            FillBuf(PSource,Length(PSource));
            Break;
          end;
        end;
      finally
        if CurBufPos<BufferSize then CurLink.Buffer[CurBufPos]:=#0;
        Result:='';
        while CurLink<>Nil do
        begin
          Result:=String(CurLink.Buffer) + Result;
          FreeMem(CurLink^.Buffer);
          PrevLink:=CurLink.Prev;
          FreeMem(CurLink);
          CurLink:=PrevLink;
        end;
      end;
    end;
      

  9.   

    函数中有个参数Buffersize,设置的越大,速度应该越快,当然越浪费空间。
      

  10.   

    我设到把BUFFERSIZE 设到了6000000,反而更慢了,要30秒左右了 :(
      

  11.   

    我在我的机子上试了humer(humer)的代码,运行时载入小文件可以,但是文件较大时发生错误,好像是超出范围之类的错误。是不是Memo控件对载入文本有大小或行数限制?要不就是由于操作系统的限制(我的机子系统是win98SE)?我试着写了个程序,用循环将数1到10000按每行一个添加到Memo,但是只添加了几千行就不能继续添加了,但也没有出错提示,请问这是怎么回事?
      

  12.   

    使用我的程序吧,很快的。
    RichEdit1.Lines.LoadFromFile(OpenDialog1.FileName);
    RichEdit1.Text:=bigReplace(RichEdit1.Text,'-','',length(RichEdit1.Text));
    txtall:=RichEdit1.Text;