Historia pytania:
Praca z plikami w języku C to fundamentalna umiejętność, która pojawiła się już w wczesnych implementacjach języka. Standardowa biblioteka C (stdio.h) oferuje uniwersalne funkcje do pracy ze strumieniami wejścia-wyjścia, co czyni programy przenośnymi między systemami operacyjnymi.
Problem:
Często początkujący programiści popełniają błędy podczas pracy z strumieniami plikowymi: nie sprawdzają wyniku otwierania plików, niewłaściwie zarządzają pamięcią dla buforowania, nie obsługują błędów przy czytaniu lub zapisywaniu. Błędy przy zamykaniu plików prowadzą do wycieków zasobów, a niepoprawna praca z buforami może prowadzić do utraty danych.
Rozwiązanie:
Aby prawidłowo pracować z plikami, zawsze należy:
fopen;fread, fwrite, fscanf, fprintf do czytania/zapisywania;fclose.Przykład kodu:
#include <stdio.h> int main() { FILE *fp = fopen("example.txt", "w"); if (!fp) { perror("Nie udało się otworzyć pliku"); return 1; } fprintf(fp, "Hello, world! "); fclose(fp); fp = fopen("example.txt", "r"); if (!fp) { perror("Błąd otwierania pliku do odczytu"); return 1; } char buffer[100]; while (fgets(buffer, sizeof(buffer), fp)) { printf("%s", buffer); } fclose(fp); return 0; }
Kluczowe cechy:
Czy można zamykać plik za pomocą fclose wiele razy pod rząd?
Nie, podwójne zamknięcie strumienia plikowego prowadzi do nieokreślonego zachowania (undefined behavior). Po fclose deskryptor staje się nieważny.
Co zwróci funkcja fread, jeśli osiągnie koniec pliku?
fread zwraca liczbę pomyślnie odczytanych elementów. Jeśli osiągnięty zostanie koniec pliku — zwracana liczba może być mniejsza od oczekiwanej. Zawsze należy sprawdzać feof i ferror dla diagnostyki.
Czy można używać tego samego strumienia plikowego do zapisu i czytania jednocześnie?
Można, jeśli plik jest otwarty w trybie "r+" lub "w+", jednak przed zmianą kierunku (zapis/czytanie) należy wykonać wywołanie fflush lub inną operację przesunięcia pozycji pliku (fseek). W przeciwnym razie zachowanie jest nieokreślone.
FILE * po fclose.fflush nie zostało wywołane, strumień nie został zamknięty).Programista zapisywał dane do pliku logu bez sprawdzania widocznej wartości od fopen. Po wyczerpaniu deskryptorów plik nie otworzył się więcej — wiadomości logów zostały utracone.
Zalety:
Wady:
W innej wersji kodu zawsze sprawdzano wszystkie wartości zwracane (fopen, fwrite, fclose). W przypadku błędu drukowano szczegółowy komunikat diagnostyczny przez perror, a program kończył się poprawnie, zwalniając wszystkie zasoby.
Zalety:
Wady: