1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| procedure TStreamSlicer.Start(S: TStream; LinesRange, LineRank: Integer);
begin
if (LinesRange < 0) or (LineRank < 0) or (LinesRange <= LineRank) then
raise Exception.Create('Spécifications numériques invalides');
if not Assigned(S) then
raise Exception.Create('Flux invalide');
FLineRank := LineRank;
FLinesRange := LinesRange;
// Normaliser le rang des lignes à retenir, doit être compris entre 0 et LineRange - 1
FLineRank := FLineRank mod FLinesRange;
FStream := S;
// Prendre le flux au début
FStream.Seek(0, soFromBeginning);
// Pas de ligne au départ
FLineNumber := 0;
NextBuffer;
End;
procedure TStreamSlicer.NextBuffer;
const
BufSize = 4096; // octets dans le buffer
var
NbRead: Integer;
begin
// Ces 3 instructions sont peut-être un peu consommatrice de CPU
// mais cela permet de travailler avec les fonctions Copy...
SetLength(FBuffer, BufSize);
NbRead := FStream.Read(FBuffer[1], BufSize);
SetLength(FBuffer, NbRead);
FCursor := 1;
FEoS := NbRead = 0;
if (not FEoS) and (FBuffer[NbRead] = #13) then
begin
// Reporte le CR à la prochaine lecture, en supprimant le CR final du buffer
FBuffer := Copy(FBuffer, 1, BufSize-1);
// Recule la position du flux sur le CR
FStream.Position := FStream.Position - 1;
end;
End;
function TStreamSlicer.NextStr: String;
var
PosEOL : Integer;
MoreLoop: Boolean;
begin
Result := '';
MoreLoop := True;
while MoreLoop do
begin
PosEOL := PosEx(CRLF, FBuffer, FCursor);
if (PosEOL > 0) and not EoS then
begin
// CR/LF trouvé
if (FLineNumber mod FLinesRange) = FLineRank then
begin
// Limiter les mouvements de mémoire
Result := Result + Copy(FBuffer, FCursor, PosEOL-FCursor);
// Arrêt de la fonction pour restitution de la ligne
MoreLoop := False;
end;
Inc(FLineNumber);
// pour la ligne suivante (après le CR/LF)
FCursor := PosEOL + 2;
end
else
begin
// on prend tout le buffer
if (FLineNumber mod FLinesRange) = FLineRank then
// Limiter les mouvements de mémoire
Result := Result + Copy(FBuffer, FCursor, MaxInt);
// et on passe au suivant, si possible
MoreLoop := not EoS;
if MoreLoop then
NextBuffer
end;
end;
End; |
Partager