お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"RE:ファイル内文字列の検索・置き換え"

この発言は
#00415 本田勝彦 さんのファイル内文字列の検索・置き換え
に対するコメントです

 検索ルーチンも外へ出しました。検索対象文字列に、改行文字 半角全角スペースタブがあってもヒットします。 大文字小文字区別無し検索も速くなりました。 例:メモのカーソル位置から検索 var Info: THitPointInfo; Buffer, P: PChar; begin Buffer := Memo1.Lines.GetText; P := Buffer; try Inc(P, Memo1.SelStart + Memo1.SelLength); if SearchBuffer(Edit1.Text, P, [sbNoMatchCase, sbIncludeCRLF, sbIncludeSpace], Info) then begin Memo1.SelStart := P - Buffer + Info.Start; Memo1.SelLength := Info.Length; Memo1.SetFocus; end; finally StrDispose(Buffer); end; end; 例:メモ内の文字列の一括置き換え var MS1, MS2: TMemoryStream; begin MS1 := TMemoryStream.Create; MS2 := TMemoryStream.Create; try Memo1.Lines.SaveToStream(MS1); MS1.Position := 0; if ReplaceStream(MS1, MS2, Edit1.Text, Edit2.Text, [sbNoMatchCase, sbIncludeCRLF, sbIncludeSpace], nil) then begin MS2.Position := 0; Memo1.Lines.LoadFromStream(MS2); end; finally MS1.free; MS2.free; end; end; ---- キリトリ ------------------------------------------------------- unit RplcStrm; // Replace Stream interface uses Windows, SysUtils, Classes; type TProgressProc = function(const StreamSize, Position: Longint): Boolean of Object; TSearchBufferOption = (sbNoMatchCase, sbIncludeCRLF, sbIncludeSpace); TSearchBufferOptions = set of TSearchBufferOption; THitPointInfo = record Start, Length: Integer; end; function SearchBuffer(const TargetText: String; P: PChar; Options: TSearchBufferOptions; var Info: THitPointInfo): Boolean; function ReplaceStream(InputStream, OutputStream: TStream; const TargetText, ReplaceText: String; Options: TSearchBufferOptions; ProgressProc: TProgressProc): Boolean; function ReplaceFile(const InputFile, OutputFile, TargetText, ReplaceText: String; Options: TSearchBufferOptions; ProgressProc: TProgressProc): Boolean; implementation function SearchBuffer(const TargetText: String; P: PChar; Options: TSearchBufferOptions; var Info: THitPointInfo): Boolean; var L, SC, C, I: Integer; Ch: Char; CharMap, UpperCharMap: array[Char] of Char; Pattern, S: String; begin Result := False; Pattern := TargetText; if sbNoMatchCase in Options then Pattern := AnsiUpperCase(Pattern); for Ch := Low(CharMap) to High(CharMap) do begin CharMap[Ch] := Ch; UpperCharMap[Ch] := Ch; end; CharUpperBuff(PChar(@UpperCharMap), SizeOf(UpperCharMap)); L := Length(Pattern); SC := StrLen(P); Info.Start := 0; while SC > 0 do begin I := 0; C := 0; Info.Length := 0; while True do begin if (I > 0) and (P[Info.Start + I + C] = #0) then Exit; if IsDBCSLeadByte(byte(P[Info.Start + I + C])) then begin S := P[Info.Start + I + C] + P[Info.Start + I + C + 1]; if sbNoMatchCase in Options then S := AnsiUpperCase(S); if S <> Copy(Pattern, I + 1, 2) then if (I > 0) and (sbIncludeCRLF in Options) and (S = #$81#$40) then begin Inc(C, 2); Inc(Info.Length, 2); Continue; end else Break; Inc(I); Inc(Info.Length); end else begin if ((sbNoMatchCase in Options) and (UpperCharMap[P[Info.Start + I + C]] <> Pattern[I + 1])) or (not (sbNoMatchCase in Options) and (CharMap[P[Info.Start + I + C]] <> Pattern[I + 1])) then if ((I > 0) and (sbIncludeCRLF in Options) and (P[Info.Start + I + C] in [#$0D, #$0A])) or ((I > 0) and (sbIncludeSpace in Options) and (P[Info.Start + I + C] in [#$20, #$09])) then begin Inc(C); Inc(Info.Length); Continue; end else Break; end; Inc(I); Inc(Info.Length); if I >= L then begin Result := True; Exit; end; end; Inc(Info.Start); Dec(SC); end; end; function ReplaceStream(InputStream, OutputStream: TStream; const TargetText, ReplaceText: String; Options: TSearchBufferOptions; ProgressProc: TProgressProc): Boolean; const BufferSize = $2000; var Buffer, P: PChar; T, R, Count, I, StreamSize: Longint; ShowProgress: Boolean; Info: THitPointInfo; begin if (InputStream = nil) or (OutputStream = nil) or (InputStream = OutputStream) or (TargetText = '') or (TargetText = ' ') or (TargetText = ' ') or (ReplaceText = '') then Exit; ShowProgress := @ProgressProc <> nil; if ShowProgress then StreamSize := InputStream.Size; T := Length(TargetText); R := Length(ReplaceText); Buffer := StrAlloc(BufferSize + 1); try P := Buffer; Info.Length := 0; while True do begin Count := InputStream.Read(P^, BufferSize - Info.Length); if Count = 0 then begin if Buffer <> P then OutputStream.Write(Buffer^, P - Buffer); Break; end else begin Buffer[Info.Length + Count] := #0; P := Buffer; while SearchBuffer(TargetText, P, Options, Info) do begin OutputStream.Write(P^, Info.Start); OutputStream.Write(ReplaceText[1], R); if Info.Length > T then for I := Info.Start to Info.Start + Info.Length do if P[I] in [#$0D, #$0A] then begin OutputStream.Write(#$0D#$0A, 2); Break; end; Inc(P, Info.Start + Info.Length); end; OutputStream.Write(P^, Info.Start); if Info.Length > 0 then begin Inc(P, Info.Start); Move(P[0], Buffer[0], Info.Length); end; P := Buffer; Inc(P, Info.Length); end; if ShowProgress then if not ProgressProc(StreamSize, InputStream.Position) then Exit; end; Result := True; finally StrDispose(Buffer); end; end; function ReplaceFile(const InputFile, OutputFile, TargetText, ReplaceText: String; Options: TSearchBufferOptions; ProgressProc: TProgressProc): Boolean; var InputStream, OutputStream: TFileStream; begin Result := False; if (InputFile = '') or (OutputFile = '') or (InputFile = OutputFile) or (TargetText = '') or (TargetText = ' ') or (TargetText = ' ') or (ReplaceText = '') then Exit; InputStream := TFileStream.Create(InputFile, fmOpenRead); OutputStream := TFileStream.Create(OutputFile, fmCreate); try Result := ReplaceStream(InputStream, OutputStream, TargetText, ReplaceText, Options, ProgressProc); finally InputStream.Free; OutputStream.Free; end; end; end. ---- キリトリ ------------------------------------------------------- 本田勝彦 Original document by 本田勝彦 氏 ID:(VYR01647)



ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum