Witam
Mam plik tekstowy, w którym zapisane może być od tysiąca do nawet około miliona linijek następnie tworze tablice, która musi mieć długość taką jak ilość linijek w pliku tekstowym i musze w jakiś bardzo szybki sposób uzyskać liczbę linijek w pliku, aby skonfigurować długość tablicy. Więc macie może jakiś szybki sposób na uzyskanie tej liczby linijek w pliku?
Nie ma trzeba przebiec po pliku i policzyc CRLF. Co zresztą nie raz było na forum.
<font color="green">//edit Ups to co poniżej jest bez sensu bo ty zdaje sie nie ładujesz tego tekstu do tej tablicy..</span>
Albo możesz lecieć w pętli repeat..until, zwiekszać wielkość tablicy powiedzmy o 1000, ładowac 1000 linijek i tak w kółko. A jak gdzieś w ostatnim obrocie plik sie skończy, to przykrawasz wielkość tablicy do ostatecznego rozmiaru. Tak zadziała szybciej niz powiększanie tablicy co 1, i być może szybciej niż najpierw policzenie CR/LF a potem tworzenie tablicy.
A dlaczego w ogóle ładujesz do tablicy a nie do TStringList?
W sumie może umieszczę kod i opisze dokładnie, o co mi chodzi mianowicie w pliku testowym mam dane zapisane w trzech kolumnach i musze je przepisać do tablicy trzy rekordowej, po czym będą zaraz po odczycie wykonywane różne operacje matematyczne na tejże tablicy. Z tym, że odczyt trwa właśnie bardzo długo a dokładniej trochę dziwnie się program zachowuje, bo za pierwszym razem, gdy chce odczytać to ten czas jest jeszcze do przyjęcia, ale za drugim, gdy wcześniej tablica była już wypełniona odczyt trwa nawet do 20s a czemu tak się dzieje nie wiem. Może ktoś będzie miał jakąś ciekawą poradę jak ten proces przyśpieszyć
type
Timpuls=packed record
im :single;
re :single;
t :single;
end;
arrimpuls=array of timpuls;
TxtImpuls=packed record //tego rekordu używam do przepisywania
im :string; //bo wtedy jest szybciej
re :string;
t :String;
end;
Procedure import(var tablica:arrimpuls; Opendialog:Topendialog);
var
f:textfile;
linijka:string; //jedna cała linijka w pliku
pierwszalinijka:string; //pierwsza linia pliku ktura zawiera inne informacje
i:integer;
cc:txtimpuls; //zmienna do przepisywania z pliku txt
BEGIN
if OpenDialog.Execute then
begin
AssignFile(f,OpenDialog.FileName);
Reset(f);
readln(f,pierwszalinijka); //czyta pierwsza linie ktora nie zawiera danych
i:=0;
DecimalSeparator:='.';
while not Eof(f) do
begin
setlength(tablica,i+1);
readln(f,linijka); //odczyt calej linijki
cc.t:='';
cc.t:=Copy(linijka,1,16); //odczyt z pierwszej kolumny
tablica[i].t:=strtofloat(cc.t);
cc.re:='';
cc.re:=Copy(linijka,17,16); //odczyt z drogiej kolumny
tablica[i].re:=strtofloat(cc.re);
cc.im:='';
cc.im:=Copy(linijka,33,length(linijka)-32);//odczyt z trzeciej kolumny
tablica[i].im:=strtofloat(cc.im);
inc(i);
end;
DecimalSeparator:=',';
closefile(f);
end;
END;
Aha no i dodam jeszcze ze właśnie za ten długi czas odczytu jest odpowiedzialna właśnie deklaracja długości tablicy, która znajduje się w pętli.
Tak jak pisałem: nie powiekszaj długości tablicy o 1, tylko w duzych paczkach. Częste powiększanie o jeden stwarza duże problemy menedżerowi pamięci, zwłaszcza, jesli tablica jest duża.
Problemy za drugim razem mogą wynikać z poszatkowania pamieci po pierwszym razie.
Ja bym probował mniej więcej tak jak poniżej (kodu nie testowałem)
Zwróc uwage, że oprócz zmiany powiekszania tablicy usunąłem zmienną cctxtimpuls, która nie jest potrzebna. Rozwaz też zmianę Timpuls z packed record na record - packed record zajmuja mniej miejsca, ale są wolniejsze.
procedure import(var tablica:arrimpuls; Opendialog:Topendialog);
var
f:textfile;
linijka:string; //jedna cala linijka w pliku
pierwszalinijka:string; //pierwsza linia pliku która zawiera inne informacje
i:integer;
const
StepSize=1000; //o tyle bedziemy zwiekszac tablice zamiast o 1, spróbuj rózne wartości
begin
if OpenDialog.Execute then
begin
AssignFile(f,OpenDialog.FileName);
Reset(f);
readln(f,pierwszalinijka); //czyta pierwsza linie ktora nie zawiera danych
DecimalSeparator:='.';
SetLenght(tablica,0) //wyczyszczenie tablicy z poprzedniego razu
repeat
SetLength(tablica,Length(Tablica)+StepSize);
for i:=High(Tablica)-Pred(StepSize) to High(Tablica) do //tu moglem sie kopnac o 1, sprawdz bo mi się nie chciało
if not Eof(f) then
begin
readln(f,linijka); //odczyt calej linijki
Tablica[i].t:=StrToFloat(Copy(linijka,1,16));
Tablica[i].re:=StrToFloat(Copy(linijka,17,16);
Tablica[i].im:=StrToFloat(Copy(linijka,33,length(linijka)-32));
//widze ze zakladasz rowna szerokosc kolumn, wtedy copy jest ok
//jesli plik bedzie mial rozne szerokosci kolumn i bedzie trzeba
// szukac po separatorach, uzyj funkcji ExtractStrings
end
else
begin
SetLength(Tablica,i); //wyrównanie nadmiarowego rozmiaru tablcy przy wychodzeniu, tu tez sprawdz blad o 1
DecimalSeparator:=',';
CloseFile(f);
Exit; //tylko tędy wychodzimy z procedury!
end;
until False;
end;
Dzięki wielkie pomogło tylko ze musze dalej używać rekordu tekstowego do przepisywania, bo jak przepisuje bezpośrednio to się kaszanka robi tak jak wcześniej, za pierwszym razem jest szybciutko a za następnymi trzeba długo czekać, lub czasami nawet nie przepisze, a czemu tak się dzieje nie wiem i przyznam ze dziwi mnie to. Ale ogólnie efekt, który chciałem nawet z tym rekordem tekstowym uzyskałem, klikom na przycisk i przepisanie teraz nie trwa nawet sekundy. Jeszcze raz dziękuje.