10 - Binární soubory

Cíle cvičení

  • Ukládaní a načítání binárních souborů.
  • Serializace.

Materiály

  • Funkce:

FILE *fopen(const char *path, const char *mode);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
int fclose( FILE *stream );

book.h

book.c

main.c

run

Z operační paměti do souboru

Poskytnutá knihovna pracuje s kolekcí struktur Book, která uchovává informace o jednotlivých svazcích. Naším úkolem je tuto kolekci uložit do (a načíst z) binárního souboru. Z paměťového hlediska chceme překopírovat bajty rozmístěné v operační paměti do sekvence (stream) bajtů reprezentované FILE.

Úkoly - Struktury a Stream bajtů

  • Načtěte ze vstupu seznam čísel a uložte je do binárního souboru. Poté soubor načtěte a vypište seznam čísel. Prohlédněte si uložený soubor programem hexdump -C nebo otevřením ve VScode (vyberte Hex Editor).
  • Naplňte strukturu Book, uložte ji jako celek do binárního souboru a prohlédněte si obsah uloženého souboru. Zkuste strukturu posléze i načíst. Hint
  • Zodpovězte si na následující otázky:
    • Ze souboru lze vyčíst hodnotu .title ale .abstract je nečitelná. Jak to? Hint
    • V souboru rozlište části reprezentující hodnoty atributů .year, .title a .abstract, odpovídá počet zapsaných bytů součtu velikostí jednotlivých atributů? Hint

Úkoly - De/Serializace dynamicky alokovaných struktur

Použijte nově nabité znalosti k implementaci knihovny:

book_serializer.h

  1. Místo ukládání struktury jako celku, uložte hodnoty jejích atributů postupně v sérii.
    1. Zařiďte ukládání řetězce .abstract, tak aby ji bylo možné načíst a přečíst. Uložení a načtení by mělo uchovat informaci zda-li .abstract=“” či .abstract=NULL. Řetězec může být libovolné délky.
    2. Soubor zas načtěte do struktury a pro ověření vypište.
    3. Diskutujte praktické rozdíly s ukládáním struktury jako celku.
  2. Implementujte nejdřív serialize_book a deserialize_book. Podobně jako u předpřipravené funkce test_list_contents(), vytvořte si v main.c další testovací funkce pro serializaci a deserializaci.
  3. Funkce na serializaci jedné knihy a funkce z rozhraní book.h pak použijte v serialize_book_list a deserialize_book_list.

Pokročilé úlohy - Závislost na platformě

V Structure Layout se dočteme, že rozložení dat ve struktuře závisí na lokální platformě (typicky na HW architektuře (např. x86-64) a operačním systému). Ve struktuře mohou být vloženy úseky nevyužitého místa (padding), které zajistí, že jednotlivé prvky se nachází na tzv. zarovnaných adresách (dělitelných specifickou konstantou). Lišit se také může lišit pořadí bytů celočíselných hodnot (tzv, endianita).

Pokud budeme přesouvat data mezi různými platformami, musíme se “dohodnout” na společné reprezentaci, se kterou budou seznámeny obě strany. Pro komunikaci přes síť (např. v IP) bylo bajtové pořadí má být big-endian (tedy platforma která přijímá data ze sítě očekává big-endian). Počítače v laboratoři naopak používají little endian (tedy obrácené pořadí).

Úkolu

  • Naprogramujte funkce le_to_be, která převede integer z little endian na big endian. (Pro uint32_t budete potřebovat stdint.h.)

uint32_t le_to_be(uint32_t v);

  • Vytvořte funkci uint32_t host_to_net32(uint32_t v), která bude převolávat le_to_be pokud hostovská platforma (zařízení na kterém je program spuštěn) používá little endian jako pořadí bajtů.
    • Řešení může být přes makro nebo lze endianitu zjišťovat dynamicky za běhu.
    • Funkčnost můžete otestovat porovnáním s
  • Nyní uložte a načtěte strukturu Book s možným přepínáním endianity.
  • Diskutujte, jak uložit hodnoty typu float nezávisle na architektuře.
courses/b0b36prp/labs/lab10.txt · Last modified: 2024/11/27 22:13 by valoudav