Q&A

  • 텍스트파일을 파싱할려고 하는데요..
텍스트 파일을 파싱할려고 합니다.
파일하나가 18메가 정도 됩니다. 문자들로 꽉꽉차여있죠.
그 스트링중에서 엔터키를 친 갯수를 구할려고 이렇게 했습니다.
버튼을 눌르면
procedure TForm1.Button2Click(Sender: TObject);
var
    happy : string;
    ea : longint;
    f : textfile;
begin
    ea := 0;
    if opendialog1.Execute then
    begin
            AssignFile(f,opendialog1.filename);
            Reset(F);
            Readln(F, happy);
            while Pos(#10, happy) > 0 do
            begin
                    happy[Pos(#10, happy)] := '^';
                    ea := ea+1;
            end;
    edit1.Text :=inttostr(ea);
    end;
end;

보시다 시피 아주 간단한 건데.. 18메가짜리 텍스트화일이라서 그런지
실행시키면 거의 다운상태에 있습니다. 15분이 지나도..그냥 잠잠.
응답없슴. 상태로 돌변합니다.
무슨 방법이 없을까요?  하드웨어적인 사양은 충분합니다.(p4,384 ram)
5  COMMENTS
  • Profile
    남양원 2002.12.19 04:15
    15분동안 응답없음 상태에서만 벗어나는 것만 알려드릴수 있겠네여...

    아래 소스에다가 표현했습니다.
       Application.ProcessMessages; 를 넣었죠...
    기대하고 보셨다면 미안합니다.

    쩝... 이상 허접 초보가....

    그리고 첨부한 파일 중에 FastStrings.Pas 파일의
    FastCharPos(const aSource: string; const C: Char; StartPos: Integer): Integer; 함수를 사용하시면 속도개선을 할 수 있을지도 모르겠습니다.
    어셈블리 코드로 되어 있거든요.....

    첨부한 파일은 여기 자료실에 찾은 겁니다. 그럼... 이만.. 꾸벅...즐프하세여



    // 여기에다가
                     Application.ProcessMessages;  // 요놈이 다른 프로그램들에게 일 할 시간을 넘겨주게 할거에요.... 쩝



  • Profile
    구창민 2002.12.19 03:58
    안녕하세요~ 구창민입니다.

    18메가라는 크기가 얼마나 영향을 줄진 모르지만,

    아래 코드를 한번 사용해 보세요.

    예전에 제가 사용한 코드인데, 속도는 보장드립니다.

    무슨 약장수 같네.. ^_^;

    function FindInFileStrCount(Str, FileName: string): integer;
    var
      Buffer: array[0..1023] of char;
      BufPtr, BufEnd: integer;
      F: file;
      Index: integer;
      Increment: integer;
      c: char;
      cnt : integer;

      function NextChar: char;
      begin
        if BufPtr >= BufEnd then
        begin
          BlockRead(F, Buffer, 1024, BufEnd);
          BufPtr:= 0;
          Application.ProcessMessages;
        end;
        Result:= Buffer[BufPtr];
        Inc(BufPtr);
      end;

    begin
      cnt := 0;
      AssignFile(F, FileName);
      Reset(F, 1);
      BufPtr:= 0;
      BufEnd:= 0;
      Index:= 0;
      Increment:= 1;
      repeat
        c:= NextChar;
        if c = Str[Increment] then
          Inc(Increment)
        else
        begin
          Inc(Index, Increment);
          Increment:= 1;
        end;
        if Increment = (Length(Str) + 1) then
        begin
          inc(cnt);
        end;
      until BufEnd = 0;
      CloseFile(F);
      result := cnt;
    end;

    //파일내에서 몇개의 문자열이 포함되어 있는지 검색한다.
    procedure TForm1.Button1Click(Sender: TObject);
    var
      ret: integer;
    begin
      //ret := FindInFileStrCount('불멸의화상','c:1.htm');
      ret := FindInFileStrCount(#10,'c:1.htm');
      ShowMessage(IntToStr(ret));
    end;



  • Profile
    안성기 2002.12.19 07:32
    저도 봤는데여..
    NextChar 만 있고 PrevChar 이 없어서
    가령 FFFnd 를 찾는 다고 할 때 dddFFFFnd 가 텍스트에 있을 때
    를 만나면 FFFF 째에서 그만두고 다시 리셋시켜서 찾아나갈꺼같은데
    그러면 dddFFFFnd 에서 nd 부터 다시 찾게 되니까
    몇개 놓치게 될거 같습니다.
    그래서 Increment - 1 만큼 PrevChar 해주는 루틴이 필요합니다..
    결국 아래의 코드를 사용하면 잘못된 결과를 출력해 줄거 같습니다.


  • Profile
    구창민 2002.12.20 23:07
    정말 그렇군여.. 하나의 글자만을 찾을땐 모르겠는데 그런 경우가 있군여..

    원래 함수를 아래처럼 수정하시면 정상 동작할겁니다.

    많은 테스트를 못해보고 올려드린점 사과 드리구여~

    그럼~ 항상 즐거운프로그래밍 하시길~~


    function FindInFileStrCount(Str, FileName: string): integer;
    var
      Buffer: array[0..1023] of char;
      BufPtr, BufEnd: integer;
      F: file;
      Index: integer;
      Increment: integer;
      c: char;
      cnt, PrevCnt : integer;

      function NextChar: char;
      begin
        if Increment = 1 then
        begin
          BufPtr := BufPtr - PrevCnt;
          PrevCnt := 0;
        end;
        if BufPtr >= BufEnd then
        begin
          BlockRead(F, Buffer, 1024, BufEnd);
          BufPtr:= 0;
          Application.ProcessMessages;
        end;
        Result:= Buffer[BufPtr];
        Inc(BufPtr);
      end;

    begin
      cnt := 0;
      PrevCnt := 0;
      AssignFile(F, FileName);
      Reset(F, 1);
      BufPtr:= 0;
      BufEnd:= 0;
      Index:= 0;
      Increment:= 1;

      repeat
        c:= NextChar;
        if c = Str[Increment] then
        begin
          Inc(Increment);
          Inc(PrevCnt);
        end
        else
        begin
          Inc(Index, Increment);
          Increment:= 1;
        end;
        if Increment = (Length(Str) + 1) then //단어를 찾은경우
        begin
          inc(cnt);
        end;
      until BufEnd = 0;
      CloseFile(F);
      result := cnt;
    end;




  • Profile
    이동현 2002.12.19 04:25
    감사합니다.

    사부로 모시고 싶습니다 ^^:
    다시 한번 감사합니다 (꾸벅)