お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





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

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

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

この発言に対し以下のコメントが寄せられています
#00433 本田勝彦 さん RE^2:ファイル内文字列の検索・置き換え

ユニット版最速バージョンです。#416, #417 はあまりにも遅かったので 削除させていただきました。お読みになられた方スミマセンm(_ _)m ---- キリトリ ------------------------------------------------------------ unit RplcStrm; // Replace Stream interface uses Windows, SysUtils, Classes; type TProgressProc = function(const StreamSize, Position: Longint): Boolean of Object; TSearchBufferOption = (sbMatchCase, 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 type TCharMap = array[Char] of Char; var UpperCharMap, AlphaCharMap: TCharMap; Ch: Char; function SearchBuffer(const TargetText: String; P: PChar; Options: TSearchBufferOptions; var Info: THitPointInfo): Boolean; var L, SC, C, I, Extend: Integer; Pattern: String; MatchChar, DBCSPattern, DBCSBuffer: Boolean; begin Result := False; Pattern := TargetText; if not (sbMatchCase in Options) then Pattern := AnsiUpperCase(Pattern); L := Length(TargetText); Info.Start := 0; SC := StrLen(P); 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; DBCSPattern := Pattern[I + 1] in [#$81..#$9F, #$E0..#$FC]; DBCSBuffer := P[Info.Start + I + C] in [#$81..#$9F, #$E0..#$FC]; if sbMatchCase in Options then if DBCSBuffer then MatchChar := DBCSPattern and (Pattern[I + 1] = P[Info.Start + I + C]) and (Pattern[I + 2] = P[Info.Start + I + C + 1]) else MatchChar := Pattern[I + 1] = P[Info.Start + I + C] else if DBCSBuffer then if (P[Info.Start + I + C] = #$82) and (P[Info.Start + I + C + 1] in [#$81..#$9A]) then // a..z MatchChar := (Pattern[I + 1] = #$82) and (Pattern[I + 2] = AlphaCharMap[P[Info.Start + I + C + 1]]) else MatchChar := DBCSPattern and (Pattern[I + 1] = P[Info.Start + I + C]) and (Pattern[I + 2] = P[Info.Start + I + C + 1]) else MatchChar := Pattern[I + 1] = UpperCharMap[P[Info.Start + I + C]]; if not MatchChar then begin Extend := 0; if I > 0 then if (sbIncludeCRLF in Options) and (P[Info.Start + I + C] in [#$0D, #$0A]) then Extend := 1 else if (sbIncludeSpace in Options) and (P[Info.Start + I + C] in [#$20, #$09]) then Extend := 1 else if (sbIncludeSpace in Options) and (P[Info.Start + I + C] = #$81) and (P[Info.Start + I + C + 1] = #$40) then Extend := 2; if Extend > 0 then begin Inc(C, Extend); Inc(Info.Length, Extend); Continue; end else Break; end else begin Inc(I, Byte(DBCSBuffer) + 1); Inc(Info.Length, Byte(DBCSBuffer) + 1); if I >= L then begin Result := True; Exit; end; end; end; Inc(Info.Start, Byte(DBCSBuffer) + 1); Dec(SC, Byte(DBCSBuffer) + 1); 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 (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 (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; initialization for Ch := Low(UpperCharMap) to High(UpperCharMap) do begin UpperCharMap[Ch] := Ch; AlphaCharMap[Ch] := Ch; end; CharUpperBuff(PChar(@UpperCharMap), SizeOf(UpperCharMap)); for Ch := #$81 to #$9A do AlphaCharMap[Ch] := Char(Ord(Ch) - $21); end. ---- キリトリ ------------------------------------------------------------ 本田勝彦 Original document by 本田勝彦 氏 ID:(VYR01647)



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

Copyright 1996-2002 Delphi Users' Forum