Ce face fread și fwrite
fwrite copiază în fișier numar elemente de câte marime octeți, exact cum sunt în memorie, fără conversie în text. fread face operația inversă. Sunt potrivite pentru tablouri de numere sau de struct; deschide fișierul cu "wb" / "rb".
Ambele returnează numărul de elemente (nu de octeți) transferate. Dacă fread returnează mai puțin decât ai cerut, fișierul s-a terminat sau a apărut o eroare (le deosebești cu feof și ferror).
Fiecare fișier deschis are o poziție curentă. fseek(f, offset, deLa) o mută: SEEK_SET de la început, SEEK_CUR de la poziția curentă, SEEK_END de la final. ftell spune poziția în octeți, iar rewind(f) revine la început. Un fișier binar scris pe un calculator poate să nu fie citit corect pe altul, dacă diferă dimensiunea tipurilor sau ordinea octeților.
Parametri
| Parametru | Descriere |
|---|---|
ptr |
Adresa datelor de scris sau a memoriei în care se citește. |
marime |
Dimensiunea unui element în octeți, de obicei sizeof. |
numar |
Câte elemente se transferă. |
offset, deLa |
La fseek: deplasarea în octeți și punctul de plecare (SEEK_SET, SEEK_CUR, SEEK_END). |
Ce returnează
fread/fwrite: numărul de elemente transferate complet. fseek: 0 la succes. ftell: poziția curentă sau -1 la eroare.
Exemple
Exemplul 1: Salvarea unui tablou de struct-uri
Trei elevi sunt scriși cu un singur apel fwrite. fseek la final și ftell dau dimensiunea fișierului: 3 elemente × 20 de octeți. Apoi rewind și fread citesc totul înapoi.
#include <stdio.h>
struct Elev {
char nume[16];
int nota;
};
int main(void) {
struct Elev clasa[] = {{"Ana", 9}, {"Mihai", 7}, {"Elena", 10}};
FILE *f = fopen("elevi.bin", "w+b");
if (f == NULL) return 0;
size_t scrise = fwrite(clasa, sizeof clasa[0], 3, f);
fseek(f, 0, SEEK_END);
printf("Elemente scrise: %zu, dimensiune fișier: %ld octeți\n", scrise, ftell(f));
rewind(f);
struct Elev citite[3];
size_t n = fread(citite, sizeof citite[0], 3, f);
for (size_t i = 0; i < n; i++) {
printf("%s: %d\n", citite[i].nume, citite[i].nota);
}
fclose(f);
return 0;
}
Rezultat
Elemente scrise: 3, dimensiune fișier: 60 octeți
Ana: 9
Mihai: 7
Elena: 10
Exemplul 2: Citirea directă a unei înregistrări
Pentru că toate înregistrările au aceeași dimensiune, a treia începe la octetul 2 * sizeof(double). fseek sare direct acolo, fără să citească ce e înainte.
#include <stdio.h>
int main(void) {
double temperaturi[] = {18.5, 21.0, 23.75, 19.25};
FILE *f = fopen("temp.bin", "wb");
if (f == NULL) return 0;
fwrite(temperaturi, sizeof(double), 4, f);
fclose(f);
f = fopen("temp.bin", "rb");
if (f == NULL) return 0;
double t;
fseek(f, 2 * (long)sizeof(double), SEEK_SET);
if (fread(&t, sizeof t, 1, f) == 1) {
printf("Ziua 3: %.2f °C (poziția acum: %ld)\n", t, ftell(f));
}
if (fread(&t, sizeof t, 1, f) == 1) {
printf("Ziua 4: %.2f °C\n", t);
}
if (fread(&t, sizeof t, 1, f) != 1 && feof(f)) {
printf("Nu mai sunt date.\n");
}
fclose(f);
return 0;
}
Rezultat
Ziua 3: 23.75 °C (poziția acum: 24)
Ziua 4: 19.25 °C
Nu mai sunt date.
Greșeli frecvente
- Scrii cu
fwriteunstructcare conține pointeri (de exempluchar *nume). În fișier ajunge adresa, nu textul, iar la citire adresa nu mai are sens. - Compari rezultatul lui
freadcu numărul de octeți. Funcția returnează numărul de elemente:fread(v, sizeof(int), 10, f)returnează cel mult 10, nu 40. - Deschizi fișierul binar fără
bpe Windows. Octeții 0x0A pot fi transformați în 0x0D 0x0A și datele se strică.
Comenzi înrudite
fopen și fclose: Deschide un fișier pentru citire, scriere sau adăugare și returnează un FILE *; fclose îl închide și salvează datele rămase.struct: Grupează mai multe valori de tipuri diferite într-un singur tip nou, de exemplu numele, vârsta și orașul unei persoane.sizeof: Operatorul care spune câți octeți ocupă un tip sau o variabilă; calculat de compilator, rezultatul are tipul size_t.memcpy: Copiază n octeți dintr-o zonă de memorie în alta; zonele nu au voie să se suprapună.fprintf: Scrie text formatat într-un fișier sau în stderr, cu același șablon ca printf.