Tablica – Importowanie danych z pliku cz.2

Tablica – Importowanie danych z pliku cz.2

Jeśli sprubujemy teraz uruchomić aplikację, to ona nie zadziała dostaniemy wyjątek NullReferenceException w miejscu, w którym chcemy iterować nasze miasta z tablicy miast a to dla tego że nie mamy jeszcze zaimplementowanej metody ReadFirstNCitys która ma pobierać miasta z pliku w tej chwili metoda zwraca tylko null.

Przejdźmy zatem do metody ReadFirstNCitys i napiszmy potrzebny nam kod.

public City[] ReadFirstNCitys(int nCitys)
{
   City[] citys = new City[nCitys];

   using (StreamReader sr = new StreamReader(_csvFilePath))
   {
      sr.ReadLine();

      for (int i = 0; i < nCitys; i++)
      {
         string csvLine = sr.ReadLine();
         citys[i] = ReadCityFromCsvLine(csvLine);
      }
   }

   return citys;
}

Co tutaj robimy. Pierwsze tworzymy instancję tablicy miast dokładnie tylu ile przekazujemy w parametrze do metody. Następnie tworzymy instancję StreamReadera, który jest typem zapewnianym przez Microsoft do odczytu plików tekstowych.

StreamReadera jest w przestrzeni nazw System.IO. Musimy podać StreamReaderowi ścieżkę do pliku do odczytania, która jest przechowywana w polu csvFilePath

StreamReader ma metodę o nazwie ReadLine, która odczytuje kolejną linię tekstu z pliku i zwraca to, co jest odczytane jako string.

Pamiętaj, że pierwszy wiersz naszego pliku CSV to wiersz nagłówka, który możemy zignorować, więc po prostu wywołuję ReadLine, ale nie robię nic z wynikiem.

Potem mamy pętlę „for”, aby przeczytać, tyle miast ile jest przekazane w parametrze nCitys. Za każdym razem w pętli pobieram następny wiersz z pliku za pomocą StreamReader.ReadLine(), a następnie analizuję ten wiersz w metodzie ReadCityFromCsvLine() której jeszcze nie mamy i zaraz ją napiszemy, aby parsować pojedynczą linię z pliku do instancji miasta. I na koniec metoda zwraca tablicę miast.

Ponieważ każda linia / wiersz pliku CSV zawiera dane dla jednego miasta, oczywistym krokiem w importowaniu pliku danych będzie konwersja pojedynczej linii z pliku do instancji jednego miasta.

Napiszmy teraz metodę ReadCityFromCsvLine() aby to zrobić.

public City ReadCityFromCsvLine(string csvLine)
{
   string[] parts = csvLine.Split(',');

   string cityName = parts[0];
   string cityCode = parts[1];
   string country = parts[2];
   int totalPopulation = int.Parse(parts[3]);
   int menPopulation = int.Parse(parts[4]);
   int womanPopulation = int.Parse(parts[5]);

   return new City(cityName, cityCode, country, totalPopulation, menPopulation, womanPopulation);
}

Metoda jako argument przyjmuje ciąg znaków, który będzie zawartością wiersza pliku i zwraca instancję miasta, którą odczytaliśmy z linii pliku csv. Więc jaka jest tutaj logika?

Bardzo Prosta. Każda linia pliku CSV zawiera nazwę miasta, kod, kraj, całkowita populacja tego miasta, populacja menzczyzn tego miasta, populacja kobiet tego miasta, oddzielone przecinkami, więc ta metoda musi podzielić ciąg, który został odczytany wszędzie tam, gdzie zawiera przecinek, abyśmy otrzymali sześć oddzielnych ciągów, reprezentujących parametry wymagane przez konstruktor miasta.

I dokładnie to robi ta metoda, string.Split(). Jest to metoda do stringów, którą Microsoft udostępnił do dzielenia stringów i tutaj doskonale pasuje do naszych celów. Metoda split analizuje coś, co wygląda jak pojedynczy przecinek.
Argument mówi metodzie Split, który znak będzie separatorem, czyli znakiem oddzielającym pola. W tym przypadku separatorem jest przecinek, ale w innym scenariuszu może to być znak tabulacji lub średnik i tak dalej.
Split podzieli ciąg, gdziekolwiek zobaczy znak separatora, i zwróci wynik, i tutaj jest interesująca rzecz.

To, co zwraca, to jest tablica ciągów. Widzisz, string.Split pobiera jeden duży ciąg i zwraca potencjalnie wiele mniejszych ciągów. Jak inaczej może zwrócić wiele innych ciągów niż w kolekcji. Kolekcje są wszędzie. Teraz jest łatwo.

Tablica zwrócona przez string.Split będzie zawierać szesc stringów odpowiadających każdej kolumnie w każdej linii CSV. Pierwsza część to miaso, druga to kod, trzecia to kraj,a czwarta to całkowita populacja tego miasta i tak dalej…

Oczywiście dostęp do tych danych uzyskujemy przy użyciu składni nawiasu kwadratowego i pamiętamy, że tablica jest indeksowana do zera. I musimy przekonwertować wszystkie populację na liczbę całkowitą i dla bezpieczeństwa używamy int.parse, co spowoduje zgłoszenie wyjątku, jeśli z jakiegokolwiek powodu te pola nie mogą zostać przeanalizowane jako liczba całkowita.

Proste, co?  Właściwie ten kod jest zbyt prosty.

Jeszcze potrzebujemy pliku population.csv

City Name,City Code,Country,Total population,Men population,Women population
Mazowieckie,MAZ,Polska,5411446,2589469,2821977
Slaskie,SLA,Polska,4524091,2180662,2343429
Wielkopolskie,WLK,Polska,3495470,1700647,1794823
WielkopolskieTest,WLK,Polska,3495470,1700647,1794823
Malopolskie,MLP,Polska,3404863,1652663,1752200
Dolnoslaskie,DOL,Polska,2899986,1394399,1505587
Lodzkie,LDZ,Polska,2460170,1172228,1287942
LodzkieTest,LDZ,Polska,2460170,1172228,1287942
PomorskieTest,POM,Polska,2337769,1138351,1199418
Pomorskie,POM,Polska,2337769,1138351,1199418
Podkarpackie,PKR,Polska,2127462,1041890,1085572
Lubelskie,LBL,Polska,2112216,1023626,1088590
Kujawsko-pomorskie,K-P,Polska,2074517,1005361,1069156
Zachodniopomorskie,ZPM,Polska,1698344,825659,872685
Warminsko-mazurskie,W-M,Polska,1425967,697504,728463
Swietokrzyskie,SWI,Polska,1237369,603304,634065
Podlaskie,PDL,Polska,1179430,574786,604644
Lubuskie,LBU,Polska,1013031,492984,520047
Opolskie,OPO,Polska,984345,476017,508328

I teraz doszliśmy do końca i możemy uruchomić nasz program!

Już prawie skończyliśmy, ale jest jeszcze jedna ostatnia rzecz, którą chcę rozwiązać.
Sposób wyświetlania tych populacji jest okropny do odczytania. Ludność Mazowieckiego wynosi w rzeczywistości 5,4 miliona, ale to, co jest tutaj wyświetlane, wygląda jak jedna duża liczba. Musisz się naprawdę skoncentrować, aby dowiedzieć się, jakie są te populacje, więc sformatujmy trochę ten wynik.

Console.WriteLine($"{city.TotalPopulation:### ### ###} : {city.CityCode} : {city.CityName}");

Całościowe omówienie tematu kolekcji (tablica, lista, kolejka, stos, słownik).
Wiele przydatnych wskazówek i dobrych praktyk dostępne jest na kursie:

https://dev-hobby.pl/kursy/c-wprowadzenie-do-kolekcji/


Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *