CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Wczytanie dużej listy adresów do komponentu TListView
Strona 1 z 1

Wczytanie dużej listy adresów do komponentu TListView

Nowy postNapisane: niedziela, 6 lutego 2011, 15:17
przez Darek_C++
Witam ponownie,
tym razem z zapytaniem o możliwość polepszenia wydajności wczytania danych do TListView.
Dane do ListView wczytuję w wątku następującym kodem:

KOD cpp:     UKRYJ  
void __fastcall WczytajZpliku::Execute()
{
        float Start = GetTickCount();
        Button->Enabled = false;
        TStringList * Lista = new TStringList();
        Lista->LoadFromFile(nazwaPliku);
        int jj = 1;

        for(int ii = 0; ii < Lista->Count; ii++)
        {
                String adres = Lista->Strings[ii].Trim();
                if(adres.IsEmpty()== false)
                {
                        TListItem * ElementListy=ListView1->Items->Add();
                        ElementListy->Caption = adres;
                        ElementListy->SubItems->Add("---");
                        ElementListy->SubItems->Add("---");
                        ++jj;
                        if((jj%100) == 0)
                        {
                                StatusBar1->Panels->Items[0]->Text="Lista zawiera "+IntToStr(jj)+" adresów";
                        }

                }
        }
        float End = GetTickCount();
        String sWCzasie = FloatToStr((End - Start) / 1000) + " s.";
        Button->Enabled = true;;

        delete Lista; Lista = NULL;
        int iDodanych = ListView1->Items->Count;
        StatusBar1->Panels->Items[0]->Text="Lista zawiera "+IntToStr(iDodanych)+" adresów. Czas wczytania: "+sWCzasie;
        StatusBar1->Panels->Items[1]->Text="---";
}
i wczytanie większych ilości dnach np 214542 adresów z pliku zajmuje bardzo dużo czasu 45 długich minut dla Release_Build :roll:

Pytanie brzmi czy idzie to przyspieszyć ?

----
Przy okazji... po kompilacji zwracana jest taka uwaga:
[C++ Warning] WatekWczytajZpliku.cpp(57): W8004 'Lista' is assigned a value that is never used
Której nie rozumiem przecież Lista jest używana w kodzie :)

Re: Wczytanie dużej listy adresów do komponentu TListView

Nowy postNapisane: niedziela, 6 lutego 2011, 16:59
przez Cyfrowy Baron
Pierwsze opóźnienie powstaje przy wczytywaniu listy do obiektu TStringList, drugie w pętli przy przepisywaniu rekordów do ListView. Pierwsze opóźnienie można wyeliminować wczytując plik bezpośrednio do ListView, bez pośrednika, np.:

KOD cpp:     UKRYJ  
 ListView1->Items->Item[0]->SubItems->LoadFromFile("Nazwa pliku.roz");


To jednak na nic się nie przyda, gdyż wczytywane są kolumny nie wiersze. Wydaje się więc, że nie ma innej metody wczytania danych do ListView niż wiersz po wierszu w pętli, ale to oznacza, że nie ma czego przyspieszyć. Pewne przyspieszenie można by uzyskać rezygnując w pętli z warunku sprawdzającego, czy rekordy są puste, oraz z inkrementacji zmiennej jj. StatusBar też można wypełnić poza pętlą sprawdzając zamiast wartości zmiennej jj liczbę elementów na liście ListView.
KOD cpp:     UKRYJ  
 TStreamReader *sReader = new TStreamReader("c:\\test.txt");

 ListView1->Items->Clear();

 while(sReader->Peek() > -1)
 {
  String adres = sReader->ReadLine();

  TListItem * ElementListy = ListView1->Items->Add();
  ElementListy->Caption = adres;
  ElementListy->SubItems->Add("---");
  ElementListy->SubItems->Add("---");
 }

 sReader->Close();
 delete sReader;


To pewnie nie będzie wiele szybsze, jestem jednak ciekaw na ile szybsze.



Przy okazji... po kompilacji zwracana jest taka uwaga:

[C++ Warning] WatekWczytajZpliku.cpp(57): W8004 'Lista' is assigned a value that is never used


Której nie rozumiem przecież Lista jest używana w kodzie :)


Komunikat sugeruje, że obiekt Lista został utworzony, ale nigdzie nie jest używany. Takie komunikaty czasami się zdarzają, ale to ostrzeżenie nie błąd, więc go po prostu zignoruj.

Re: Wczytanie dużej listy adresów do komponentu TListView

Nowy postNapisane: niedziela, 6 lutego 2011, 17:35
przez Darek_C++
Nie mogę sprawdzić z powodu:

[C++ Error] WatekWczytajZpliku.cpp(34): E2451 Undefined symbol 'TStreamReader'


Widocznie Turbo C++ nie ma tej klasy :(
-----
Samo przejście w pętli z sprawdzaniem: if(adres.IsEmpty()== false)
w wyświetlaniem :
if((jj%100) == 0)
{
StatusBar1->Panels->Items[0]->Text="Lista zawiera "+IntToStr(jj)+" adresów";
}
Zajmuje tylko, 0.8 sekundy więc narzut czasowy na to jest pomijalni mały. W przeciwieństwie do wczytywanie do TListView :(

Re: Wczytanie dużej listy adresów do komponentu TListView

Nowy postNapisane: poniedziałek, 7 lutego 2011, 11:08
przez polymorphism
W przypadku list view jedyny i efektywny sposób przyśpieszenia wczytywania danych, to przełączenie go w tryb wirtualny. W trybie tym list view nie trzyma danych, jedynie je wyświetla (w wątku z czytaniem plików CSV podałem przykład aplikacji czytającej do grida działającego w tym trybie. 1700000 wierszy w 10 sekund [z możliwością przyśpieszenia :)]).

Właściwość TListView::OwnerData przełącza list view w tryb wirtualny.

____
p.s. to są te same adresy z tematu o duplikatach?

Re: Wczytanie dużej listy adresów do komponentu TListView

Nowy postNapisane: poniedziałek, 7 lutego 2011, 11:37
przez Cyfrowy Baron
Zajmuje tylko, 0.8 sekundy więc narzut czasowy na to jest pomijalni mały. W przeciwieństwie do wczytywanie do TListView :(


Jest to jednak zbędne, gdyż ListView zwraca ilość wierszy, więc dodatkowe wyliczanie rekordów jest niepotrzebne:

KOD cpp:     UKRYJ  
StatusBar1->Panels->Items[0]->Text="Lista zawiera " + IntToStr(ListView1->Items->Count) + " adresów";

Re: Wczytanie dużej listy adresów do komponentu TListView

Nowy postNapisane: poniedziałek, 7 lutego 2011, 12:41
przez Darek_C++
Cyfrowy Baron napisał(a):Jest to jednak zbędne, gdyż ListView zwraca ilość wierszy, więc dodatkowe wyliczanie rekordów jest niepotrzebne:
To nie jest zbędne gdyż wizualizuje postęp wczytywania danych do ListView 'a :) Poza tym tam nic dodatkowo nie zlicza tylko wyświetla ile wczytano pod koniec odczytując właściwość:
int iDodanych = ListView1->Items->Count;

polymorphism napisał(a):W przypadku list view jedyny i efektywny sposób przyśpieszenia wczytywania danych, to przełączenie go w tryb wirtualny.
p.s. to są te same adresy z tematu o duplikatach?
Ustawiłem właściwość na ListView1->OwnerData = true;
I w przy tym ustawieniu 91230 lini z pliku wczytuje się w 39 sekund, dla porównania z OwnerData = false 521 sekund ;

Ale w tym trybie nie mam wizualnej prezentacji danych w ListView1 wiec co mi to daje - kontener dla danych ?

Tak, mowa o listach adresów www takich jak "z tematu o duplikatach"

Re: Wczytanie dużej listy adresów do komponentu TListView

Nowy postNapisane: poniedziałek, 7 lutego 2011, 13:02
przez polymorphism
Ale w tym trybie nie mam wizualnej prezentacji danych w ListView1 wiec co mi to daje ?

Musisz zaimplementować obsługę odpowiednich zdarzeń, m.in. OnData. W tym trybie nie dodajesz elementów w taki sam sposób, jak robisz to w zwykłym trybie. Jedynie ustawiasz ilość elementów, a list view przy odświeżeniu widoku będzie Cię prosić o dane elementu, który ma zamiar narysować w kontrolce.

kontener dla danych ?

Wręcz przeciwnie. Jeszcze raz napiszę: w tym trybie kontrolka nie przechowuje elementów, jedynie je wyświetla. Zatem aplikacja w pełni zarządza danymi. Dzięki temu masz pełną kontrolę nad tym, jak i gdzie wczytujesz dane.

Re: Wczytanie dużej listy adresów do komponentu TListView

Nowy postNapisane: poniedziałek, 7 lutego 2011, 14:32
przez Darek_C++
Tylko jak to wszystko obsłużyć :zawiedziony: Nawet przesunięcie suwakiem wymaga osobnej obsługi danych.