Hi,
following the advice of howardpc, I repost here my question from the forum (https://forum.lazarus.freepascal.org/index.php/topic,60287.0.html).
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?
Ciao,
Gilles Marcou
Below is a sketch of the modifications.
1. Add a list of line start positions in the stream:
Code: Pascal [Select][+]
1.
TListInt64 = specialize TFPGList<Int64>;2.
(...)
3.
TStreamReader = class(TTextReader)
4.
private5.
flPos: TListInt64;6.
function ReadPos(Idx: integer): Int64;7.
procedure WritePos(Idx: integer; AValue: Int64);8.
(...)
9.
public10.
property lPos[Idx: integer]: Int64 read ReadPos write WritePos;11.
2. Manage this list
Code: Pascal [Select][+]
1.
function TStreamReader.ReadPos(Idx: integer): Int64;2.
begin3.
Result:=flPos[Idx];4.
end;5.
6.
procedure TStreamReader.WritePos(Idx: integer; AValue: Int64);7.
begin8.
flPos[idx]:=AValue;9.
end;10.
11.
constructor TStreamReader.Create(AStream: TStream; ABufferSize: Integer;12.
AOwnsStream: Boolean);13.
begin14.
(...)
15.
flPos:=TListInt64.Create;16.
end;17.
18.
procedure TStreamReader.Close;19.
begin20.
(...)
21.
FreeAndNil(flPos);22.
end;23.
3. Store line start positions
Code: Pascal [Select][+]
1.
procedure TStreamReader.ReadLine(out AString: string);2.
var3.
VPByte: PByte;4.
VPosition, VStrLength, VLength: Integer;5.
begin6.
flPos.Add(FBufferPosition);7.
4. Add a procedure to jump to the desired line
Code: Pascal [Select][+]
1.
procedure GoToLn(n: integer);2.
(...)
3.
procedure TStreamReader.GoToLn(n: integer);4.
var5.
apos: Int64;6.
begin7.
apos:=flPos[n-1];//flPos is 0-based and lines are 1-based8.
Reset;9.
FStream.Seek(apos,soBeginning);10.
end;11.
