Zapis danych z pliku do tablicy

0

Witam, mam problem z szybkoscia dzialania mojego programu. Napisalem taki kod ktory odczytuje dane z pliku i zapisuje go odpowiednio do tablicy:

var
  g:TFileStream;
  tb:TStrings;
  buf: array of char;   
  n:integer;
begin
 if Opendialog1.Execute then
    if OpenDialog1.FileName<>'' then
      try
        g:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
        n:=g.Size;
        SetLength(buf,n);
        g.ReadBuffer(buf[0],n);
        tb:=TStringList.Create;
        SetLength(tablica,0,0);

        ExtractStrings([#10,','],[],Pansichar(buf),tb);
        time:=0;
        repeat
            SetLength(tablica,high(tablica)+2,8);
            wioski[high(tablica),0]:=tb.Strings[0+(7*high(tablica))];
            wioski[high(tablica),1]:=tb.Strings[1+(7*high(tablica))];
            wioski[high(tablica),2]:=tb.Strings[2+(7*high(tablica))];
            wioski[high(tablica),3]:=tb.Strings[3+(7*high(tablica))];
            wioski[high(tablica),4]:=tb.Strings[4+(7*high(tablica))];
            wioski[high(tablica),5]:=tb.Strings[5+(7*high(tablica))];
            wioski[high(tablica),6]:=tb.Strings[6+(7*high(tablica))];
         until (high(tablica)=tb.Count-1);
      finally
        g.Free;
      end;
end;

wszystko pieknie i ladnie ale za wolno [!!!]

Podejrzewam ze wszystko rozegra sie o ta petle repeat, ale czym to zastapic zeby dane z strings byly wpisane odpowiednio do tablicy? znacie moze jakies metody?

dodam iz plik wyglada mniej wiecej tak:

1,abc,0,100,100,100,100#102,abc,0,100,100,100,100#103,abc,0,100,100,100,100#104,abc,0,100,100,100,100#105,abc,0,100,100,100,100#10
inaczej zapisujac bedzie cos takiego:

1,abc,0,100,100,100,100
2,abc,0,100,100,100,100
3,abc,0,100,100,100,100
4,abc,0,100,100,100,100
5,abc,0,100,100,100,100

chodzi o to zeby odczytac wartosci i zapisac je do tablicy w miare szybko (ponad 100 000 linijek).

0

Mnie się wydaje , że wiele zrobić się nie da, to znaczy odczyt 100000 stringów i przekopiowanie ich musi troche trwac. Poza jednym szczegółem. Mianowicie rozmiar tablicy "tablica" lepiej ustalic przed pętlą repeat by go nie zwiększac w każdym przebiegu tej pętli. Bedzie na pewno troche szybciej (a może nawet sporo szybciej).
Poza tym lepiej wprowadzić jakąś zmienną iterującą tę pętlę i tej zmiennej używać do indeksowania zamiast wywołania high(tablica), które o ile się nie mylę jest wywołaniem funkcji więc jest wolniejsze niż odwołanie do zmiennej. Ponadto jesli nie powoduje to problemów to zawsze lepiej użyć pętli for niż repeat until, tym bardziej że w tej pętli for od razu mamy ową zmienną iterującą.

Inna sprawa to nie wiem czy masz pewność, że ten kod działa długo tylko z powodu samej pętli repeat. Mnie się wydaje, że przy tak dużej liczbie stringów funkcja ExtractStrings tez musi działać pewien niekrótki czas a z tego co napisałeś to każdy string o ile dobrze rozumiem jest tej samej długości a to znaczy, że można te informacje wykorzystać i do podziału odczytanego z dysku bufora na stringi użyć np. funkcji move i to będzie moim zdaniem szybsze niż ExtractStrings, która to funkcja nie znając długości musi przeszukiwac bufor znak po znaku.

0

OMG [!!!]
chlopie dzieki wielkie! :D odczytane w 3sek? ^^ nie sadzilem ze zmieniajac high(wioski) na i , i wyrzucajac SetLength przed petle repeat mozna az tyle zmienic :o
kod teraz wyglada mniej wiecej tak:

var
  g:TFileStream;
  tb:TStrings;
  buf: array of char;   
  n,i:integer;
begin
 if Opendialog1.Execute then
    if OpenDialog1.FileName<>'' then
      try
        g:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
        n:=g.Size;
        SetLength(buf,n);
        g.ReadBuffer(buf[0],n);
        tb:=TStringList.Create;
        SetLength(tablica,0,0);
        ExtractStrings([#10,','],[],Pansichar(buf),tb);
        SetLength(tablica,tb.count div 7,8);
        i:=-1;
        repeat
            inc(i);
            tablica[i,0]:=tb.Strings[0+(7*i)];
            tablica[i,1]:=tb.Strings[1+(7*i)];
            tablica[i,2]:=tb.Strings[2+(7*i)];
            tablica[i,3]:=tb.Strings[3+(7*i)];
            tablica[i,4]:=tb.Strings[4+(7*i)];
            tablica[i,5]:=tb.Strings[5+(7*i)];
            tablica[i,6]:=tb.Strings[6+(7*i)];
         until (i=(tb.Count div 7)-1);
      finally
        g.Free;
      end;
end;

no i program dziala blyskawicznie ;] taka drobnostka -.-'
Moze sie komus to przyda :)

0

No to miło mi, że mogłem pomóc. Powodzenia:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1