Obsługa plików w C++ – odczyt danych

Pisząc programy komputerowe na pewno, każdy kiedyś zetknął się z obsługą plików. To właśnie między innymi dzięki plikom, możemy zapisywać ważne informacje wykorzystywane w naszym programie co podniesie jego użyteczność. Po co zresztą komuś aplikacja, która nie potrafi zapamiętać wcześniej wprowadzonych informacji?

Obsługa plików w C++ nie jest tak bardzo skomplikowana jak mogło by się wydawać początkującym programistom, w niniejszym artykule zaprezentuję na praktycznych przykładach sposoby odczytu danych z plików tekstowych oraz binarnych.

Pliki możemy odczytywać za pomocą bibliotek fstreamstdio.h, które zanim zaczniemy cokolwiek robić musimy najpierw zaimportować do naszego programu:

Kiedy już dołączyliśmy którąś z bibliotek na przykład fstream to możemy się zabrać do dalszej pracy.

getline()

Napiszmy sobie program, który pobiera dane z pliku tekstowego linijka po linijce za pomocą funkcji getline(); i wypisuje je na ekranie. Funkcja getline(uchwytDoPliku, dane); pobiera jedną linijkę z pliku tekstowego.

Powyższy program wyświetli nam na ekranie zawartość danego pliku tekstowego pobierając wszystkie dane linijka po linijce.

Otwieranie pliku za pomocą funkcji fopen()

Korzystając z biblioteki stdio.h będziemy korzystali z funkcji fopen() do otwarcia pliku. Zobaczmy jak się nią posługiwać:

Ogólna składnia funkcji fopen():

Za scierzkaDoPliku.txt wstawiamy ścieżkę do pliku który chcemy otworzyć względem naszego pliku z kodem, a w miejscu parametru określamy tryb dostępu do pliku:

Tryb dostępu do pliku Opis
a Otwiera plik tylko do zapisu (jeśli plik nie został stworzony, to zostanie utworzony, wszystkie nowe dane będą zapisywane na jego końcu)
a+ Otwiera plik do odczytu i zapisu (jeśli plik nie został stworzony, to zostanie utworzony, wszystkie nowe dane będą zapisywane na jego końcu, można odczytywać dowolny fragment pliku)
b Otwiera plik w trybie binarnym
r Otwiera plik tylko do odczytu (wcześniej musi on zostać stworzony)
r+ Otwiera plik do odczytu i zapisu (wcześniej musi on zostać stworzony, można odczytywać i zapisywać dowolny fragment pliku)
w Tworzy nowy plik i otwiera tylko do zapisu (uchwyt ustawiany jest na samym początku, a w przypadku kiedy dany plik już istniał to kasowana jest jego zawartość)
w+ Tworzony nowy plik i otwiera go do odczytu i zapisu (uchwyt ustawiany jest na samym początku, a w przypadku kiedy dany plik już istniał to kasowana jest jego zawartość, można odczytywać i zapisywać dowolny fragment pliku)

Przykład:

fgetc()

Oczywiście możemy na przykład chcieć pobierać tekst z danego pliku znak po znaku. Problem ten można rozwiązać na przykład wykorzystując bibliotekę stdio.h i funkcję fgetc();. Osobiście wolę właśnie używać tej biblioteki do obsługi plików w C++ gdyż metoda ta jest znacznie szybsza oraz mam większą kontrolę nad pobieranymi danymi i wykonywanymi operacjami.

Napiszmy więc program, który będzie pobierał dane z pliku tekstowego znak po znaku.

Funkcja fopen(„plik”, „trybOtwarcia”); może otwierać pliki w różnych trybach, na przykład do odczytu lub zapisu. Sposób działania tej funkcji omówiłem w poprzednim akapicie „Otwieranie pliku za pomocą funkcji fopen()„.

fgets()

Funkcja fgets() odczytuje dane z wybranego wejścia (na przykład pliku) do momentu napotkania znaku nowej linii bądź do momentu wczytania określonej liczby znaków.

Przykład:

Ogólna składnia funkcji fgets():

fscanf()

fscanf() działa bardzo podobnie do scanf(). Funkcję fscanf() można jednak wykorzystać do odczytania danych z pliku. Przyjrzyjmy się więc jak to zrobić.

Przykład:

Ogólna składnia:

W miejscu specyfikator podajemy dane z poniżej tabelki:

Specyfikator Opis
%d lub %i Liczba całkowita ze znakiem (system dziesiętny) np. int
%f Liczba rzeczywista (system dziesiętny) np. float
%u Liczba całkowita bez znaku (system dziesiętny)
%e Liczba w notacji naukowej – ze znakiem e (małe litery)
%E Liczba w notacji naukowej – ze znakiem E (duże litery)
%g Liczba rzeczywista w notacji %f lub %e
%G Liczba rzeczywista w notacji %f lub %E
%o Liczba w systemie ósemkowym
%x Liczba w systemie szesnastkowym (małe litery)
%X Liczba w systemie szesnastkowym (duże litery)
%c Znak np. zmienne typu char
%s Łańcuch znaków zakończony “\0“, np. zmienne typu string
%p Adres pamięci

fread()

Napiszmy teraz program, który odczyta nam dane z pliku binarnego.

W powyższym programie do odczytu danych binarnych została wykorzystana funkcja fread();, której składnia wygląda następująco:

Jak widać nie ma w tym nic trudnego.

Fot: Alexandre Buisse (Nattfodd).

, , , , , , , , , , , ,

  • W fopen określamy nie tylko tryb dostępu do pliku, ale również rodzaj pliku – domyślnie otwierany jest tryb tekstowy, należałoby dodac ‚b’, aby był tryb binarny

    Do wczytywania danych w c masz jeszcze fgets i fscanf, nie tylko fgetc
    natomiast w fstream nie tylko jest getline.

    Dodatkowo fstream nie do końca jest uchwytem, jest całym obiektem z mnogością metod (nie omijając operatorów <>)

    • Dzięki, w najbliższym czasie postaram się zaktualizować artykuł o podane przez Ciebie elementy. Natomiast jeśli chodzi o fstream to już poprawiłem ;)

      • Miałeś dodać ‚b’, czyli powinno być np „rb” :)

        • Dodałem „b” do tabelki jako osobny tryb otwierania pliku (tryb binarny)

          • nie chodzi o tabelkę, a o uzycie:
            plik = fopen(„plik.dat”, „b”); //otwarcie pliku jako plik binarny – parametr „b”

            winno być:
            plik = fopen(„plik.dat”, „rb”); //otwarcie pliku jako plik binarny – parametr „b”

          • Faktycznie, dzięki ;)

  • Pola

    Obsługa plików w C++ nie jest tak bardzo skomplikowana jak mogło by się wydawać początkującym programistOM!!

    • Ta forma też jest dopuszczalna: http://sjp.pl/programist%C4%85

      • Pola

        ale nie w tym kontekscie.

        – Kim jestem? – Jestem programistą.

        – Komu się przyglądam? – Przyglądam się pracującym programistom.

        • Ok, prawiłem ;) Tego typu błędów niestety nie wyłapuje edytor.

  • do
    {
    getline(uchwyt, linia); //pobierz linijkę
    cout << linia << endl; //wypisz na ekranie
    }
    while(linia == ""); //przerwij jeżeli linia będzie pusta (dane w pliku się skończą)

    Pyt.: Czy ten warunek while (linia == "") nie oznacza "powtarzaj pętelę jeżeli linia jest pusta"? Nie rozumiem dlaczego taki warunek miałby oznaczać, że w linii coś się znajduje. Ktoś wyjaśni?

    • Faktycznie tam powinno być while(linia != „”), wtedy mamy false w momencie, w którym trafimy na pustą linijkę – ważne jest, żeby taka była na końcu bo inaczej program będzie się wykonywał w nieskończoność.