Ho un file di testo che leggo per intero, per poi elaborarlo in vario modo. Metto tutte le linee dentro un’Array. Ma quante sono le linee lo so solo dopo averlo letto. Ma devo dimensionare l’array prima di leggerlo. Per cui che fare?
1) si esagera, mettendo una setlength enorme, per poi ridurla dopo aver letto il file
2) come faccio da un po' di tempo, leggo il file di testo una prima volta solo per determinare il numero delle linee, dimensiono l’array e poi rileggo il file di testo per metterlo nell’array.
3) mettere una setlength un po’ di più del comune (ritenendo che una enorme comprometta le risorse del computer) però rischiando di andare in overflow (mi è successo)
Ciao,
non sono sicuro di aver capito la domanda, comunque, se è come ho capito, non devi per forza dimensionare l'array a priori, puoi aumentare di volta in volta la sua dimensione.
Qui un esempio in cui, leggendo un file di testo, andavo a salvarmi i dati in un array:
procedure TForm1.VerificaCsv(NomeCsv: String);
type TTipoPosizDate = array of Integer;
const ChrSost='^';
ChrDaCerc=#0;
var St, StOrig, StrTestata:String;
f:TextFile;
ListaWrk:TStringList;
PosizDate:TTipoPosizDate;
VFPrimaRiga, VFFileDaElaborare, VFDataOk, VFPrimoErrore:Boolean;
Idx, IdxArray:Integer;
begin
//Inizializzazione variabili di lavoro
VFPrimoErrore:=True;
VFPrimaRiga:=True;
VFFileDaElaborare:=True;
AssignFile(f, UTF8ToSys(NomeCsv));
FileMode:=CstApriFileSolaLett;
try
Reset(f);
while (not Eof(f)) and
VFFileDaElaborare do begin
Readln(f, St);
StOrig:=St;
//Scompongo la stringa nei suoi elementi principali
ListaWrk:=TStringList.Create;
try
ScomponiStringa(';', St, ListaWrk, True, False);
//Se è la prima riga, valorizzo l'array in cui mi salvo le posizioni dei campi
//di tipo data nel CSV
if VFPrimaRiga then begin
VFPrimaRiga:=False;
StrTestata:=StOrig;
PosizDate:=nil;
IdxArray:=0;
for Idx:=0 to ListaWrk.Count - 1 do begin
St:=UpperCase(ListaWrk[Idx]);
System.Delete(St, 1, Pos('_', St));
if (Copy(St, 1, 4) = 'DATA') then begin
SetLength(PosizDate, IdxArray + 1);
PosizDate[IdxArray]:=Idx;
Inc(IdxArray);
end;
end;
//Se il file non ha nemmeno una data, è inutile proseguire !!!
if (IdxArray = 0) then begin
VFFileDaElaborare:=False;
end;
end else begin
VFDataOk:=True;
for Idx:=Low(PosizDate) to High(PosizDate) do begin
if VFDataOk then begin
if (not DataOk(ListaWrk[PosizDate[Idx]])) then begin
VFDataOk:=False;
end;
end;
end;
//Se almeno una delle date non è corretta, lo segnalo
if (not VFDataOk) then begin
if VFPrimoErrore then begin
VFPrimoErrore:=False;
Memo1.Lines.Add('');
Memo1.Lines.Add(NomeCsv);
Memo1.Lines.Add(StrTestata);
end;
//Se il file contiene caratteri #0, lo segnalo
if (Pos(ChrDaCerc, StOrig) > 0) then begin
StOrig:=StringReplace(StOrig, ChrDaCerc, ChrSost, [rfReplaceAll]);
Memo1.Lines.Add(' ==> La riga seguente conteneva caratteri #0, sostituiti con ' + ChrSost);
end;
Memo1.Lines.Add(' '+ StOrig);
end;
end;
finally
PulisciLista(ListaWrk, tpFree);
end;
end;
finally
CloseFile(f);
end;
end;
In particolare, in questo pezzettino qui, all'inizio l'array è a nil, e la sua dimensione è 0.
Poi, per ogni dato buono che trovo, aumento di 1 la dimensione
PosizDate:=nil;
IdxArray:=0;
for Idx:=0 to ListaWrk.Count - 1 do begin
St:=UpperCase(ListaWrk[Idx]);
System.Delete(St, 1, Pos('_', St));
if (Copy(St, 1, 4) = 'DATA') then begin
SetLength(PosizDate, IdxArray + 1);
PosizDate[IdxArray]:=Idx;
Inc(IdxArray);
end;
end;
Ciao, Mario