Dear community,
recently I wanted to rewind a file to read again a previous line. After some search I came to the conclusion to modify the TStreamReader class. Do you think that would be a useful addition? Should it be an a modification to TStreamReader or a new class?
Below is a sketch of the modifications.
1. Add a list of line start positions in the stream:
TListInt64 = specialize TFPGList<Int64>;
(...)
TStreamReader = class(TTextReader)
private
flPos: TListInt64;
function ReadPos(Idx: integer): Int64;
procedure WritePos(Idx: integer; AValue: Int64);
(...)
public
property lPos[Idx: integer]: Int64 read ReadPos write WritePos;
2. Manage this list
function TStreamReader.ReadPos(Idx: integer): Int64;
begin
Result:=flPos[Idx];
end;
procedure TStreamReader.WritePos(Idx: integer; AValue: Int64);
begin
flPos[idx]:=AValue;
end;
constructor TStreamReader.Create(AStream: TStream; ABufferSize: Integer;
AOwnsStream: Boolean);
begin
(...)
flPos:=TListInt64.Create;
end;
procedure TStreamReader.Close;
begin
(...)
FreeAndNil(flPos);
end;
3. Store line start positions
procedure TStreamReader.ReadLine(out AString: string);
var
VPByte: PByte;
VPosition, VStrLength, VLength: Integer;
begin
flPos.Add(FBufferPosition);
4. Add a procedure to jump to the desired line
procedure GoToLn(n: integer);
(...)
procedure TStreamReader.GoToLn(n: integer);
var
apos: Int64;
begin
apos:=flPos[n-1];//flPos is 0-based and lines are 1-based
Reset;
FStream.Seek(apos,soBeginning);
end;