unit StrStrm; interface uses SysUtils, Classes; const DEFAULT_PAGE_SIZE = 65536; // 64k type TStringStreamer = class private fStream: TFileStream; fFileName: string; fPageSize: integer; fPagesLoaded: integer; fLinesRead: integer; fStr: string; fLen: integer; fOffset: integer; fLastPage: boolean; protected procedure LoadNextPage; property Stream: TFileStream read fStream; property LastPage: boolean read fLastPage; public constructor Create(const AFileName: string; AShare: boolean = true; APageSize: integer = DEFAULT_PAGE_SIZE); destructor Destroy; override; procedure Reset; function NextLine: string; function Eof: boolean; property FileName: string read fFileName; property PageSize: integer read fPageSize; property PagesLoaded: integer read fPagesLoaded; property LinesRead: integer read fLinesRead; end;//of class implementation { ### TStringFile ############################################################ } constructor TStringStreamer.Create(const AFileName: string; AShare: boolean = true; APageSize: integer = DEFAULT_PAGE_SIZE); begin fFileName:=AFileName; if APageSize <= 0 then APageSize:=DEFAULT_PAGE_SIZE; fPageSize:=APageSize; if AShare then fStream:=TFileStream.Create(AFileName,fmOpenRead or fmShareDenyWrite) else fStream:=TFileStream.Create(AFileName,fmOpenRead or fmShareExclusive); SetString(fStr,nil,ApageSize); LoadNextPage; end; destructor TStringStreamer.Destroy; begin fStream.Free; inherited; end; { ### protected ### } procedure TStringStreamer.LoadNextPage; begin fStr[1]:=#0; fLen:=Stream.Read(pointer(fStr)^,fPageSize); fOffset:=1; fLastPage:=fLen < fPageSize; inc(fPagesLoaded); end; { ### public ### } procedure TStringStreamer.Reset; begin Stream.Position:=0; fPagesLoaded:=0; LoadNextPage; fLinesRead:=0; end; function TStringStreamer.NextLine: string; label CONTINUE_LINE; var Prev: string; P: PChar; Start: PChar; FullLine: boolean; S: string; begin Prev:=''; Result:=''; CONTINUE_LINE: FullLine:=false; P:=@fStr[fOffset]; Start:=P; while fOffset <= fLen do begin if P^ in [#0, #10, #13] then begin FullLine:=true; Break; end; inc(P); inc(fOffset); end; SetString(S,Start,P-Start); if FullLine then begin if pointer(Prev) <> nil then Result:=Prev+S else Result:=S; if P^ = #13 then begin inc(P); inc(fOffset); end; if P^ = #10 then begin inc(P); inc(fOffset); end; if P^ = #0 then begin //inc(P); inc(fOffset); end; end else begin if pointer(Prev) <> nil then Prev:=Prev+S else Prev:=S; if not Eof then begin LoadNextPage; goto CONTINUE_LINE end else Result:=Prev; end; inc(fLinesRead) end; function TStringStreamer.Eof: boolean; begin Result:=LastPage and (fOffset > fLen); end; { ############################################################################ } end.