Laborator 9: Operaţii cu fişiere. Aplicaţii folosind fişiere.
Obiectivele laboratorului
În acest laborator vom studia:
- tipuri de fișiere: binare și text
- operații cu fiecare tip de fișier: deschidere/închidere, citire/scriere, poziționare
- aplicații: probleme de bază cu tablouri și structuri (vom aprofunda în laboratorul următor)
ATENȚIE! Toate sarcinile se vor realiza folosind o abordare modularizată (cu funcții). Discutați cu asistentul alegerile voastre, dacă nu sunteți siguri care ar trebui să fie semnăturile funcțiilor.
TOATE exercițiile vor fi verificate și cu valgrind.
Materiale utile:
Exerciții
- [intro-to-files] Scrieți un program care:
-
să scrie într-un fișier numele (maxim 30 de caractere) și vârsta unui student (datele sunt citite de la tastatură)
-
să închidă fișierul creat
-
să îl deschidă pentru citire
-
să închidă fișierul
a. Fișierele folosite sunt text.
Observație: Pentru un fișier text putem folosi utilitare uzuale (ex. cat) pentru a verifica conținutului.
Exemplu de rulare: Input (stdin): gigel 69 Output (1-gen.txt): gigel 69 Output (stdout - dupa redeschiderea fisierului): saved_name = "gigel" saved_age = 69
b. Fișierele folosite sunt binare.
Observație: Pentru analiza fișierelor binare, vom folosi utilitarele hexdump sau xxd.
Reprezentare aleasă: datele se vor scrie în continuare (fără delimitatori)
- un int se va scrie ca o înșiruire de
sizeof(int)
bytes - un string se va reprezenta prin 2 componente
- lungime (int) (inclusiv
\0
) - șir de octeți (inclusiv
\0
)
- lungime (int) (inclusiv
Exemplu de rulare: Input (stdin): gigel 69 Output (hexdump -C 1-gen.bin): 00000000 06 00 00 00 67 69 67 65 6c 00 45 00 00 00 |....gigel.E...| 0000000e Output (stdout - dupa redeschiderea fisierului): saved_name = "gigel" saved_age = 69
Observăm că în dreapta hexdump oferă și o reprezentare textuală pentru bytes.
Explicație exemplu
Presupunem că
sizeof(int) == 4
și ca sistemul folosește convențiaLittle-Endian
În fișier vom scrie- Nume:
- Lungime: 6 =
0x00.00.00.06
=>06 00 00 00
(înlittle-endian
) - Șirul: {'g', 'i', 'g', 'e', 'l', '\0'} =>
67 69 67 65 6c 00
(Conform tabelei ASCII) - Vârsta: 69 = 0x00.00.00.45 => 45 00 00 00
- Lungime: 6 =
- un int se va scrie ca o înșiruire de
-
[random-output] Se citeasc
n
și un șir den
numere de la tastatură. Să se creeze un fișier în care să se salveze doar celen
elemente (fără dimensiunea șirului).a. Fișierul generat este text:
Exemplu de rulare: Input (stdin): 5 10 1 -1 2 257 Output (2-gen.txt): 10 1 -1 2 257
b. Fișierul generat este binar:
Exemplu de rulare: Input (stdin): 5 10 1 -1 2 257 Output(hexdump -C 2-gen.bin): 00000000 0a 00 00 00 01 00 00 00 ff ff ff ff 02 00 00 00 |................| 00000010 01 01 00 00 |....| 00000014
Explicație
- 10 =
0x00.00.00.0a
=>0a 00 00 00
- 1 =
0x00.00.00.01
=>01 00 00 00
- -1 =
0xff.ff.ff.ff
=>ff ff ff ff
- 2 =
0x00.00.00.02
=>02 00 00 00
- 257 =
0x00.00.01.01
=>01 01 00 00
- 10 =
- [random-input] Se dă un fișier cu un număr nedeterminat de numere (de tip int). Se cere să se scrie un program care:
-
să citească toate numerele din fișier pentru a determina câte elemente sunt în fișier
-
să repoziționeze cursorul la începutul fișierului pentru a putea citi din nou elementele și a le salva într-un vector alocat dinamic
-
să afișeze lungimea și șirul stocate în memorie
Se vor folosi pentru testare fișierele generate la exercițiul 2:
a. Fișierul folosit este de tip text.
b. Fișierul folosit este de tip binar.
Exemplu de rulare: Input (2-gen.txt/bin): 10 1 -1 2 257 Output (stdout): n = 5 10 1 -1 2 257
-
[BONUS] [sizeof-file] Să se scrie o funcție care primește ca parametru numele unui fișier și returnează dimensiunea în bytes a acestuia. Să se realizeze un program pentru testare (numele fișierului e citit de la tastatură).
Observație: Putem folosi utilitarul ls (cu flagul -l) pentru a verifica dimensiunea fișierelor din directorul corect.
$ ls -al total 120 drwxr-xr-x 5 darius darius 4096 Nov 19 00:48 . drwxr-xr-x 8 darius darius 4096 Nov 18 20:55 .. -rw-r--r-- 1 darius darius 1246 Nov 19 00:08 1-bin.c -rw-r--r-- 1 darius darius 12 Nov 19 00:22 1-gen.bin -rw-r--r-- 1 darius darius 13 Nov 18 23:37 1-gen.txt -rw-r--r-- 1 darius darius 755 Nov 19 00:08 1-text.c -rw-r--r-- 1 darius darius 517 Nov 19 00:22 2-bin.c -rw-r--r-- 1 darius darius 20 Nov 19 00:28 2-gen.bin -rw-r--r-- 1 darius darius 12 Nov 19 00:22 2-gen.txt -rw-r--r-- 1 darius darius 507 Nov 19 00:31 2-text.c -rw-r--r-- 1 darius darius 788 Nov 19 00:42 3-bin.c -rw-r--r-- 1 darius darius 822 Nov 19 00:35 3-text.c -rw-r--r-- 1 darius darius 484 Nov 19 00:48 4-sizeof_file.c -rwxr-xr-x 1 darius darius 16888 Nov 19 00:48 a.out -rwxr-xr-x 1 darius darius 16888 Nov 19 00:48 sizeof_file # Compilare program $ gcc 4-sizeof_file.c -o sizeof_file # Determinare dimensiune pentru a.out $ ./sizeof_file a.out a.out has 16888 bytes # Determinare dimensiune pentru sizeof_file $ ./sizeof_file sizeof_file sizeof_file has 16888 bytes # Determinare dimensiune pentru 3-bin.c $ ./sizeof_file 3-bin.c 3-bin.c has 788 bytes