Einzelnen Beitrag anzeigen

aegidos

Registriert seit: 30. Okt 2007
40 Beiträge
 
Delphi 2007 Professional
 
#1

Find and Replace in Textfile

  Alt 20. Aug 2009, 10:47
Hy alle zusammen.

Ich habe hier im Forum einen überaus hilfreichen Beitrag zum Suchen und Ersetzen gefunden:
Hier im Forum suchenReplaceInFile
Delphi-Quellcode:
function TTestProgrammDlg.ReplaceInFile(const FileName, SearchString, NewString: AnsiString;
  CaseSensitive: Boolean): Longint;
  { returns position of string in file or -1, if not found }
const
  BufferSize = $8001; { 32K+1 bytes }
var
  pBuf, pEnd, pScan, pPos: PAnsiChar;
  filesize: LongInt;
  bytesRemaining: LongInt;
  bytesToRead: Integer;
  F: file;
  SearchFor: PAnsiChar;
  oldMode: Word;
begin
  Result := -1; { assume failure }
  // NEW (first line): if length of string to search and new string does not match, cancel.
  // Of course one could move the rest of the file accordingly instead.
  if (Length(SearchString) <> Length(NewString))
    or (Length(SearchString) = 0) or (Length(FileName) = 0) then Exit;
  SearchFor := nil;
  pBuf := nil;

  { open file as binary, 1 byte recordsize }
  AssignFile(F, FileName);
  oldMode := FileMode;
  FileMode := fmOpenReadWrite; { NEW: access to read and write }
  Reset(F, 1);
  FileMode := oldMode;
  try
    { allocate memory for buffer and pchar search string }
    SearchFor := StrAlloc(Length(SearchString) + 1);
    StrPCopy(SearchFor, SearchString);
    if not caseSensitive then { convert to upper case }
      AnsiUpper(SearchFor);
    GetMem(pBuf, BufferSize);
    filesize := System.Filesize(F);
    bytesRemaining := filesize;
    pPos := nil;
    while bytesRemaining > 0 do
    begin
      { calc how many bytes to read this round }
      if bytesRemaining >= BufferSize then
        bytesToRead := Pred(BufferSize)
      else
        bytesToRead := bytesRemaining;

      { read a buffer full and zero-terminate the buffer }
      BlockRead(F, pBuf^, bytesToRead, bytesToRead);
      pEnd := @pBuf[bytesToRead];
      pEnd^ := #0;
       { scan the buffer. Problem: buffer may contain #0 chars! So we
         treat it as a concatenation of zero-terminated strings. }

      pScan := pBuf;
      while pScan < pEnd do
      begin
        if not caseSensitive then { convert to upper case }
          AnsiUpper(pScan);
        pPos := StrPos(pScan, SearchFor); { search for substring }
        if pPos <> nil then
        begin { Found it! }
          Result := FileSize - bytesRemaining +
            Longint(pPos) - Longint(pBuf);

          // NEW: replace it
          Seek(F, Result);
          BlockWrite(F, PAnsiChar(NewString)^, Length(NewString));
          Break;
        end;
        pScan := StrEnd(pScan);
        Inc(pScan);
      end;
      if pPos <> nil then Break;
      bytesRemaining := bytesRemaining - bytesToRead;
      if bytesRemaining > 0 then
      begin
       { no luck in this buffers load. We need to handle the case of
        the search string spanning two chunks of file now. We simply
        go back a bit in the file and read from there, thus inspecting
        some characters twice
       }

        Seek(F, FilePos(F) - Length(SearchString));
        bytesRemaining := bytesRemaining + Length(SearchString);
      end;
    end; { While }
  finally
    CloseFile(F);
    if SearchFor <> nil then StrDispose(SearchFor);
    if pBuf <> nil then FreeMem(pBuf, BufferSize);
  end;
end; { ScanFile }
Diese Funktion sucht das erste Auftauchen des Searchstrings und ersetzt diesen im gegebenen File durch den NewString.
Wie muss man denn diese Funktion anpassen um jedes Vorkommen des Searchstrings zu ersetzen?

Danke für die Hilfe!
Andi
  Mit Zitat antworten Zitat