Często podczas pracy programu chcielibyśmy wczytać dane lub zapisać wyniki jego działania. Dotychczas wszystkie potrzebne informacje do działania aplikacji wprowadzaliśmy ręcznie lub umieszczaliśmy na stałe w programie. Jednak język C++ pozwala nam na operowanie na plikach - tworzyć nowe pliki i zapisywać do nich informacje, odczytywać dane. Spróbujemy dziś utworzyć plik tekstowy, w skład którego będzie wchodzić 10 wierszy. W każdym wierszu zapiszemy dwie liczby całkowite oddzielone spacją. Liczby wczytamy do tablicy liczb całkowitych. Do pliku wynikowego zapiszemy większą z liczb w danej parze. Wynik zapiszemy do pliku. Każdą parę w osobnym wierszu (w przypadku równości). Pisanie programu zaczniemy od przygotowania pliku tekstowego na którym będziemy pracować. Zapisanie pliku folderze z plikami źródłowymi pozwoli zachować porządek w strukturze projektu. Nazwa pliku jest dowolna, jednak musimy pamiętać o wprowadzeniu jej jako napisu do kodu programu - długa nazwa może doprowadzić do niepotrzebnej literówki. Nasz plik uzupełniamy zgodnie z poleceniem. Dziesięcioma wierszami składającymi się z par liczb oddzielonych spacją. 1 20 12 2 34 12 3 54 11 4 77 44 5 3 5 6 1 9 7 43 76 8 98 68 9 10 67 10 33 99 Czas na implementację naszego kodu. Zaczniemy od umieszczenia odpowiednich bibliotek które pozwolą nam zarządzać naszymi plikami. Biblioteka iostream dodaje funkcjonalność pracy na strumieniach danych wejścia i wyjścia. Dzięki niej mogliśmy wypisać komunikaty na konsoli, a także wczytać dane od użytkownika. Biblioteka fstream dodaje funkcjonalność pracy na strumieniach plików. Upraszcza zarządzanie plikami, pozwalając na odczyt i zapis danych w sposób zbliżony do dotychczasowej pracy z konsolą. Zaczniemy od najprostszego scenariusza który sprawdzi czy wszystko działa, a plik jest poprawnie otwierany przez aplikację. Zmienna typu fstream przechowuje informacje o pliku - gdzie jest umieszczony, w jakim trybie został otwarty. który fragment pliku został już odczytany. Otwierając plik C++ oznacza go w systemie operacyjnym jako używany, nie pozwalając na przeniesienie czy usunięcie. Funkcja open wywołana na zmiennej typu fstream otwiera plik. Wymaga wskazania dwóch argumentów: ścieżki do pliku (może być zarówno względna, jak i bezwzględna) oraz trybu pracy, czyli jakie operacje będą wykonywane na pliku. Przykład: plik.open("./moj_plik.txt", fstream::in); 1 #include 2 #include 3 4 using namespace std; 5 6 int main() 7 { 8 string wiersz; 9 fstream plik_odczyt; 10 plik_odczyt.open("do_odczytu.txt", fstream::in); 11 12 if(plik_odczyt.good() == true) 13 { 14 while(!plik_odczyt.eof()) 15 { 16 getline(plik_odczyt, wiersz); 17 cout << wiersz << endl; 18 } 19 20 plik_odczyt.close(); 21 } 22 23 return(0); 24 } 25 Na konsoli widzimy prawidłowy wydruk. Skoro poznaliśmy już podstawy możemy wczytać nasze liczby do tablicy. Dzięki dodaniu do biblioteki fstream praca na plikach jest zbliżona do wcześniej poznanych operacji na strumieniach. Odczyt danych z pliku polega na skierowaniu przepływu strumienia od pliku do zmiennej, do której chcemy zapisać dane. Przykład: plik >> zmienna; Musimy pamiętać, że odczytując dane z pliku z wykorzystaniem strumieni, C++ nie odczytuje całej linii! Dzieli ją na mniejsze części składające się z napisów znajdujących się między wybranymi znakami niedrukowanymi, np. spacjami. Zdanie "Ala ma kota" zostanie podzielone na trzy części: "Ala, "ma", "kota". Nasz kod po zmiananach wygląda tak: 1 #include 2 #include 3 4 using namespace std; 5 6 int main() 7 { 8 string wiersz; 9 fstream plik_odczyt; 10 plik_odczyt.open("do_odczytu.txt", fstream::in); 11 12 int liczby[10][2]; 13 int iterator = 0; 14 15 if(plik_odczyt.good() == true) 16 { 17 while (!plik_odczyt.eof()) 18 { 19 plik_odczyt >> liczby[iterator][0] >> liczby[iterator][1]; 20 cout << liczby[iterator][0] << " " << liczby[iterator][1] << endl; 21 iterator++; 22 } 23 24 plik_odczyt.close(); 25 } 26 27 return(0); 28 } 29 Na konsoli pojawia się dokładnie ten sam wydruk co wcześniej więc nasza aplikacja działa poprawnie. Udało się nam odczytać dane, spróbujemy je teraz zapisać do pliku. Utworzenie strumienia do pliku, w którym mają być zapisane dane, sprowadza się do otwarcia pliku w trybie out. Jeżeli plik nie istnieje na dysku, zostanie automatycznie utworzony. Jeżeli plik istnieje na dysku, jego zawartość zostaje nadpisana. Nasz program po zmianach: 1 #include 2 #include 3 4 using namespace std; 5 6 int main() 7 { 8 string wiersz; 9 fstream plik_odczyt; 10 plik_odczyt.open("do_odczytu.txt", fstream::in); 11 12 int liczby[10][2]; 13 int iterator = 0; 14 15 if(plik_odczyt.good() == true) 16 { 17 while (!plik_odczyt.eof()) 18 { 19 plik_odczyt >> liczby[iterator][0] >> liczby[iterator][1]; 20 cout << liczby[iterator][0] << " " << liczby[iterator][1] << endl; 21 iterator++; 22 } 23 24 plik_odczyt.close(); 25 } 26 27 fstream plik_zapis; 28 plik_zapis.open("do_zapisu.txt", fstream::out); 29 30 if(plik_zapis.good() == true) 31 { 32 for(int i = 0; i < 10; i++) 33 { 34 int wieksza = liczby[i][0] > liczby[i][1] ? liczby[i][0] : liczby[i][1]; 35 plik_zapis << wieksza << " "; 36 } 37 plik_zapis.close(); 38 } 39 40 return(0); 41} Po uruchomieniu programu wewnątrz folderu z zawartością projektu powinniśmy zauważyć nowy pliki, przechowujący większą z liczb każdej pary wejściowej. Podsumowując. W języku C++ obsługę plików zapewnia biblioteka fstream. Przed przystąpieniem do jakiejkolwiek operacji na pliku należy go otworzyć, podając ścieżkę wraz z trybem otwierania: in (odczyt danych), out (zapis danych), binarny (tryb binarny). Pojedynczą linię odczytujemy za pomocą funkcji getline (plik, zmiennaDoZapisania). Dane z pliku możemy odczytać za pomocą strumieni: plik >> zmienna. Dane do pliku możemy zapisać za pomocą strumieni: plik << zmienna.