Operacje na plikach

Wyjaśnienie operacji na plikach

Operacje na plikach obejmują zestaw działań umożliwiających przechowywanie, odczytywanie, modyfikowanie i usuwanie danych w plikach zapisanych na dysku. Kluczowe operacje to:

  1. Otwarcie pliku – zanim plik może być używany, należy go otworzyć, określając tryb dostępu (np. tylko do odczytu, do zapisu, do dopisywania).

  2. Odczyt z pliku – umożliwia pobranie danych z pliku do pamięci programu. Odczyt może odbywać się znak po znaku, linia po linii lub w postaci binarnej.

  3. Zapis do pliku – pozwala na umieszczenie danych w pliku, co może nadpisać istniejącą zawartość lub dopisać nowe dane na końcu pliku.

  4. Zamknięcie pliku – po zakończeniu operacji na pliku należy go zamknąć, aby zwolnić zasoby systemowe.

  5. Obsługa błędów – operacje na plikach mogą się nie powieść z różnych powodów (np. brak dostępu, nieistniejący plik), dlatego należy sprawdzać status operacji.

  6. Usuwanie i zmiana nazwy pliku – pozwala na zarządzanie plikami poprzez ich kasowanie lub modyfikację nazwy.

Operacje na plikach są powszechnie wykorzystywane w aplikacjach do przechowywania danych użytkownika, konfiguracji programów, logowania zdarzeń czy przetwarzania dużych zbiorów danych.

Zastosowanie operacji na plikach w C++

Otwarcie pliku

Aby pracować z plikami w C++, należy użyć biblioteki <fstream>, która umożliwia operacje wejścia i wyjścia na plikach. Do otwarcia pliku wykorzystuje się obiekty ifstream (dla odczytu) i ofstream (dla zapisu), ewentualnie fstream (dla odczytu i zapisu).

#include <fstream>
using namespace std;

ifstream plikOdczyt("dane.txt");  // Otwarcie pliku do odczytu
ofstream plikZapis("wyniki.txt"); // Otwarcie pliku do zapisu

Zapis do pliku

Aby zapisać dane do pliku, wystarczy użyć operatora <<, podobnie jak w przypadku cout.

ofstream plik("wyniki.txt"); 
plik << "To jest zapisany tekst." << endl;
plik.close();  // Zamknięcie pliku po zakończeniu operacji

Odczyt z pliku

Dane można odczytywać przy użyciu operatora >> (dla pojedynczych wartości) lub metody getline() (dla całych linii tekstu).

ifstream plik("dane.txt");
string linia;

while (getline(plik, linia)) {
    cout << linia << endl;
}
plik.close();

Odczyt całej zawartości pliku za pomocą eof()

Możemy odczytać plik aż do jego końca, wykorzystując eof(), który zwraca true, gdy osiągniemy koniec pliku.

ifstream plik("dane.txt");
string linia;

while (!plik.eof()) {
    getline(plik, linia);
    cout << linia << endl;
}
plik.close();

Sprawdzanie poprawności otwarcia pliku

Aby uniknąć błędów, warto sprawdzić, czy plik został poprawnie otwarty.

ifstream plik("nieistniejacy.txt");
if (!plik) {
    cout << "Błąd otwarcia pliku!" << endl;
} else {
    cout << "Plik otwarty poprawnie." << endl;
}

Poruszanie się po pliku: seekg() i seekp()

Funkcje seekg() (dla odczytu) i seekp() (dla zapisu) pozwalają na przemieszczanie wskaźnika odczytu/zapisu w pliku.

fstream plik("dane.txt", ios::in | ios::out);

// Przemieszczenie wskaźnika odczytu na 10. bajt od początku pliku
plik.seekg(10, ios::beg); 

// Przemieszczenie wskaźnika zapisu na koniec pliku
plik.seekp(0, ios::end); 

plik.close();

Usuwanie i zmiana nazwy pliku

Można również usuwać pliki (remove()) i zmieniać ich nazwy (rename()).

remove("staryPlik.txt");  
rename("plikTymczasowy.txt", "nowaNazwa.txt");

Podsumowanie

Operacje na plikach w C++ pozwalają na trwałe przechowywanie i przetwarzanie danych. Możemy otwierać pliki w różnych trybach, odczytywać i zapisywać dane, poruszać się po pliku, sprawdzać błędy oraz zarządzać plikami.

Przykłady zastosowań operacji na plikach

Przykład 1 - Zapisywanie i odczytywanie danych z pliku

W tym przykładzie zademonstrowano, jak otworzyć plik, zapisać do niego dane, a następnie odczytać jego zawartość w języku C++.

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    // Tworzenie i zapis do pliku
    ofstream plikZapis("dane.txt"); // Otwarcie pliku do zapisu
    if (!plikZapis) {
        cout << "Blad otwarcia pliku do zapisu!" << endl;
        return 1;
    }
    
    plikZapis << "Jan Kowalski" << endl;
    plikZapis << "28" << endl;
    plikZapis.close(); // Zamkniecie pliku po zakonczeniu zapisu

    // Odczyt z pliku
    ifstream plikOdczyt("dane.txt"); // Otwarcie pliku do odczytu
    if (!plikOdczyt) {
        cout << "Blad otwarcia pliku do odczytu!" << endl;
        return 1;
    }
    
    string imie, nazwisko;
    int wiek;
    
    plikOdczyt >> imie >> nazwisko >> wiek; // Odczytanie danych
    plikOdczyt.close(); // Zamkniecie pliku po zakonczeniu odczytu

    // Wyswietlenie odczytanych danych
    cout << "Dane odczytane z pliku:" << endl;
    cout << "Imie: " << imie << ", Nazwisko: " << nazwisko << ", Wiek: " << wiek << endl;

    return 0;
}

Działanie:

  1. Otwarcie pliku i zapis danych
    Program tworzy plik dane.txt i zapisuje do niego przykładowe dane: imię, nazwisko oraz wiek użytkownika. Po zakończeniu zapisu plik zostaje zamknięty.

  2. Otwarcie pliku do odczytu
    Plik dane.txt jest otwierany w trybie odczytu. Program sprawdza, czy udało się go poprawnie otworzyć.

  3. Odczyt danych z pliku
    Z pliku wczytywane są imię, nazwisko i wiek użytkownika, a następnie plik zostaje zamknięty.

  4. Wyświetlenie odczytanych informacji
    Program wypisuje na ekranie odczytane dane w uporządkowanej formie.

Wynik działania programu:

Dane odczytane z pliku:
Imie: Jan, Nazwisko: Kowalski, Wiek: 28

Podsumowanie:

Ten przykład pokazuje, jak można zapisywać i odczytywać dane z pliku w języku C++. Obsługa plików jest kluczowa w programowaniu, ponieważ umożliwia trwałe przechowywanie i przetwarzanie informacji.

Przykład 2 - Dopisywanie danych do pliku i odczyt całej zawartości

W tym przykładzie zademonstrowano, jak dopisać nowe dane do istniejącego pliku i odczytać całą jego zawartość.

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main() {
    // Otwarcie pliku w trybie dopisywania
    ofstream plikZapis("dane.txt", ios::app); // Tryb ios::app dopisuje dane na koncu pliku
    if (!plikZapis) {
        cout << "Blad otwarcia pliku do zapisu!" << endl;
        return 1;
    }
    
    // Dopisanie kolejnych danych do pliku
    plikZapis << "Anna Nowak" << endl;
    plikZapis << "24" << endl;
    plikZapis.close(); // Zamkniecie pliku po zakonczeniu zapisu

    // Odczyt calej zawartosci pliku linia po linii
    ifstream plikOdczyt("dane.txt"); // Otwarcie pliku do odczytu
    if (!plikOdczyt) {
        cout << "Blad otwarcia pliku do odczytu!" << endl;
        return 1;
    }

    cout << "Zawartosc pliku:" << endl;
    string linia;
    
    while (getline(plikOdczyt, linia)) { // Odczyt kazdej linii az do konca pliku
        cout << linia << endl;
    }

    plikOdczyt.close(); // Zamkniecie pliku po odczycie

    return 0;
}

Działanie:

  1. Dopisanie nowych danych do pliku

    • Plik dane.txt jest otwierany w trybie dopisywania (ios::app), dzięki czemu nowe dane nie nadpisują istniejącej zawartości, a są dodawane na końcu.

    • Dopisywane są kolejne informacje: "Anna Nowak" i "24".

  2. Odczytanie całej zawartości pliku

    • Plik jest otwierany w trybie odczytu, a program sprawdza, czy otwarcie było udane.

    • Zawartość pliku jest odczytywana linia po linii za pomocą getline() aż do końca pliku (EOF).

  3. Wyświetlenie danych

    • Program wypisuje zawartość pliku na ekran.

Wynik działania programu:

Jeśli dane.txt przed uruchomieniem programu zawierało:

Jan Kowalski
28

to po wykonaniu programu jego nowa zawartość będzie:

Jan Kowalski
28
Anna Nowak
24

a wynik wyświetlony na ekranie:

Zawartość pliku:
Jan Kowalski
28
Anna Nowak
24

Podsumowanie:

Ten przykład pokazuje, jak można dopisywać dane do pliku bez ich nadpisywania oraz jak odczytać całą jego zawartość. Jest to szczególnie przydatne, gdy chcemy rejestrować historię danych, np. w dziennikach zdarzeń lub listach użytkowników.

Przykład 3 - Poruszanie się po pliku za pomocą seekg() i seekp()

W tym przykładzie zademonstrowano, jak poruszać się po pliku przy użyciu funkcji seekg() i seekp(), które pozwalają na zmianę pozycji kursora odczytu i zapisu.

#include <iostream>
#include <fstream>

using namespace std;

int main() {
    // Tworzenie i zapis do pliku
    fstream plik("dane.bin", ios::out | ios::binary);
    if (!plik) {
        cout << "Blad otwarcia pliku do zapisu!" << endl;
        return 1;
    }

    // Zapisanie liczb do pliku binarnego
    int liczby[] = {10, 20, 30, 40, 50};
    plik.write(reinterpret_cast<char*>(liczby), sizeof(liczby));
    plik.close(); // Zamkniecie pliku po zapisie

    // Otworzenie pliku do odczytu
    fstream plikOdczyt("dane.bin", ios::in | ios::binary);
    if (!plikOdczyt) {
        cout << "Blad otwarcia pliku do odczytu!" << endl;
        return 1;
    }

    int liczba;
    
    // Przesunięcie kursora na trzecia liczbe (indeks 2)
    plikOdczyt.seekg(2 * sizeof(int), ios::beg);  
    plikOdczyt.read(reinterpret_cast<char*>(&liczba), sizeof(int));

    cout << "Trzecia liczba w pliku: " << liczba << endl;

    plikOdczyt.close(); // Zamkniecie pliku po odczycie

    return 0;
}

Działanie programu:

  1. Zapis do pliku binarnego:

    • Program tworzy plik dane.bin i zapisuje w nim tablicę liczb {10, 20, 30, 40, 50} w formie binarnej.

    • Dane są zapisywane za pomocą write().

  2. Poruszanie się po pliku:

    • Plik jest ponownie otwierany w trybie odczytu binarnego.

    • Kursor odczytu jest przesuwany za pomocą seekg() na trzecią liczbę (2 * sizeof(int), ponieważ indeksy zaczynają się od 0).

    • Program odczytuje tę liczbę za pomocą read() i wyświetla ją na ekranie.

  3. Wyświetlenie wyniku:

    • Program wypisuje wartość trzeciej liczby zapisanej w pliku.

Wynik działania programu:

Trzecia liczba w pliku: 30

Podsumowanie:

Ten przykład pokazuje, jak można manipulować pozycją kursora w pliku za pomocą seekg() (dla odczytu) i seekp() (dla zapisu). Jest to przydatne w pracy z plikami binarnymi, gdzie konieczne jest szybkie przechodzenie do określonych pozycji w pliku.

Przykład 4 - Usuwanie i zmiana nazwy pliku

W tym przykładzie zademonstrowano, jak usunąć plik oraz zmienić jego nazwę przy użyciu funkcji remove() i rename().

#include <iostream>
#include <cstdio> // Biblioteka do operacji na plikach (remove, rename)

using namespace std;

int main() {
    const char* nazwaPliku = "przykladowy.txt";
    const char* nowaNazwaPliku = "zmieniona_nazwa.txt";

    // Tworzenie pliku testowego
    FILE* plik = fopen(nazwaPliku, "w");
    if (plik) {
        fputs("To jest testowy plik.\n", plik);
        fclose(plik);
        cout << "Plik '" << nazwaPliku << "' zostal utworzony." << endl;
    } else {
        cout << "Blad podczas tworzenia pliku!" << endl;
        return 1;
    }

    // Zmiana nazwy pliku
    if (rename(nazwaPliku, nowaNazwaPliku) == 0) {
        cout << "Plik zostal pomyslnie zmieniony na '" << nowaNazwaPliku << "'." << endl;
    } else {
        cout << "Blad podczas zmiany nazwy pliku!" << endl;
        return 1;
    }

    // Usuniecie pliku
    if (remove(nowaNazwaPliku) == 0) {
        cout << "Plik '" << nowaNazwaPliku << "' zostal usuniety." << endl;
    } else {
        cout << "Blad podczas usuwania pliku!" << endl;
        return 1;
    }

    return 0;
}

Działanie programu:

  1. Tworzenie pliku:

    • Program otwiera plik "przykladowy.txt" w trybie zapisu ("w").

    • Zapisuje w nim przykładowy tekst.

    • Zamykany plik po zapisie.

  2. Zmiana nazwy pliku:

    • Używana jest funkcja rename(), która zmienia nazwę "przykladowy.txt" na "zmieniona_nazwa.txt".

    • W przypadku błędu wyświetlany jest komunikat.

  3. Usuwanie pliku:

    • Funkcja remove() usuwa plik "zmieniona_nazwa.txt".

    • Jeśli operacja się powiedzie, wyświetlany jest odpowiedni komunikat.

Wynik działania programu:

Plik 'przykladowy.txt' zostal utworzony.
Plik zostal pomyslnie zmieniony na 'zmieniona_nazwa.txt'.
Plik 'zmieniona_nazwa.txt' zostal usuniety.

Podsumowanie:

Ten przykład ilustruje, jak w C++ można programowo zmieniać nazwy plików oraz je usuwać. Funkcje rename() i remove() należą do standardowej biblioteki C i mogą być używane do podstawowych operacji na plikach w systemie plików.

Zadania - operacje na plikach w C++

Zadanie 1 - Podstawowe operacje na plikach w C++

Napisz program w C++, który wykonuje podstawowe operacje na plikach. Program będzie odczytywał dane z pliku i wyświetlał je na ekranie.

Kroki do wykonania:

  1. Stwórz plik tekstowy dane.txt, który będzie zawierał następujące dane:

    Jan Kowalski 25
    Anna Nowak 30
    Piotr Zieliński 28
  2. Zdefiniuj zmienne do przechowywania danych odczytanych z pliku: imie, nazwisko, wiek.

  3. Otwórz plik dane.txt w trybie odczytu.

  4. Odczytaj dane z pliku i zapisz je do zmiennych.

  5. Wyświetl dane na ekranie.

Wynik działania programu:

Imię: Jan, Nazwisko: Kowalski, Wiek: 25
Imię: Anna, Nazwisko: Nowak, Wiek: 30
Imię: Piotr, Nazwisko: Zieliński, Wiek: 28

Zadanie 2 - Tworzenie, usuwanie i zmiana nazwy pliku

Napisz program w C++, który pozwala użytkownikowi na trzy operacje na plikach:

  • utworzenie nowego pustego pliku,

  • usunięcie istniejącego pliku,

  • zmianę nazwy pliku.

Kroki do wykonania:

  1. Zapytaj użytkownika, jaką operację chce wykonać:

    • 1 - Utworzyć nowy plik,

    • 2 - Usunąć istniejący plik,

    • 3 - Zmienić nazwę pliku.

  2. Jeśli użytkownik wybierze utworzenie pliku:

    • Poproś o nazwę nowego pliku.

    • Utwórz pusty plik przy użyciu ofstream.

    • Zamknij plik i wyświetl komunikat o powodzeniu.

  3. Jeśli użytkownik wybierze usunięcie pliku:

    • Poproś o nazwę pliku do usunięcia.

    • Sprawdź, czy plik istnieje.

    • Jeśli istnieje, usuń go za pomocą remove().

    • Wyświetl komunikat o powodzeniu lub błędzie.

  4. Jeśli użytkownik wybierze zmianę nazwy pliku:

    • Poproś o aktualną nazwę pliku i nową nazwę.

    • Sprawdź, czy plik istnieje.

    • Jeśli istnieje, zmień jego nazwę za pomocą rename().

    • Wyświetl komunikat o powodzeniu lub błędzie.

Przykład działania programu:

Wybierz operację:
1 - Utwórz nowy plik
2 - Usuń plik
3 - Zmień nazwę pliku
Twój wybór: 1

Podaj nazwę nowego pliku: nowy_plik.txt

Plik 'nowy_plik.txt' został utworzony.
Wybierz operację:
1 - Utwórz nowy plik
2 - Usuń plik
3 - Zmień nazwę pliku
Twój wybór: 2

Podaj nazwę pliku do usunięcia: dane.txt

Plik 'dane.txt' został usunięty.
Wybierz operację:
1 - Utwórz nowy plik
2 - Usuń plik
3 - Zmień nazwę pliku
Twój wybór: 3

Podaj nazwę pliku do zmiany: stare_dane.txt
Podaj nową nazwę pliku: archiwum.txt

Plik został pomyślnie zmieniony na 'archiwum.txt'.

Zadanie 3 - Tworzenie pliku i dopisywanie danych

Napisz program w C++, który tworzy plik tekstowy, zapisuje do niego dane o osobach, a następnie umożliwia dopisanie nowych danych.

Kroki do wykonania:

  1. Sprawdź, czy plik dane.txt istnieje.

    • Jeśli nie istnieje, utwórz go i zapisz przykładowe dane:

      Jan Kowalski 25
      Anna Nowak 30
    • Jeśli plik istnieje, dopisz do niego kolejne osoby.

  2. Zdefiniuj strukturę Osoba, która będzie przechowywać: imie, nazwisko, wiek.

  3. Zapytaj użytkownika, czy chce dopisać nową osobę do pliku.

    • Jeśli tak, pobierz dane od użytkownika i dopisz je do pliku.

  4. Wyświetl zawartość pliku po dopisaniu nowych danych.

Przykład działania programu:

Plik dane.txt nie istnieje. Tworzenie pliku i zapis przykładowych danych...
Czy chcesz dodać nową osobę? (t/n): t
Podaj imię: Piotr
Podaj nazwisko: Zieliński
Podaj wiek: 28

Dane w pliku po dopisaniu:
Imię: Jan, Nazwisko: Kowalski, Wiek: 25
Imię: Anna, Nazwisko: Nowak, Wiek: 30
Imię: Piotr, Nazwisko: Zieliński, Wiek: 28