Best practice - Načítání binární hlavičky do struktury – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Best practice - Načítání binární hlavičky do struktury – C / C++ – Fórum – Programujte.comBest practice - Načítání binární hlavičky do struktury – C / C++ – Fórum – Programujte.com

 

PiranhaGreg0
Stálý člen
27. 3. 2015   #1
-
0
-

Zdravím,

řekněme že mám např. takovouto strukturu binární hlavičky nějakého souboru 

typedef struct {
	uint16_t chans;
	uint32_t freq;
	uint32_t ssize;
	uint32_t blck;
	uint64_t resv;
	uint16_t amplt[256];
} MUSHeader;

a zajímalo by mě, jak se v praxi načítá. Vždycky mě totiž láká něco jako 

fread(&header, sizeof(MUSHeader), 1, file);

což je sice elegantní řešení, kvůli různýmu paddingu ale ne správný. Nakonec tedy skončím u něčeho jako 

fread(&header.chans, sizeof(header.chans), 1, file);
fread(&header.freq, sizeof(header.freq), 1, file);
fread(&header.ssize, sizeof(header.ssize), 1, file);
fread(&header.blck, sizeof(header.blck), 1, file);
fread(&header.resv, sizeof(header.resv), 1, file);
fread(&header.amplt, sizeof(header.amplt), 1, file);

což už se mi tak moc nelíbí. Navíc systémová volání jsou časově relativně drahá záležitost. Ještě mě napadlo načíst si to celý do paměti a pak to z ní postupně přiřazovat, ale to by bylo docela složitý.

Takže jak se to teda v praxi řeší efektivně i efektně?  

Nahlásit jako SPAM
IP: 2001:718:2:2905:e088:b68a...–
Judegarek0
Newbie
27. 3. 2015   #2
-
0
-

Mě to funguje i když to mám nezarovnaný.

#include <inttypes.h>
#include <stdio.h>
#include <string.h>

typedef struct
{
    uint16_t chans;
    uint32_t freq;
    uint32_t ssize;
    uint32_t blck;
    uint64_t resv;
    uint8_t bla;
    uint16_t amplt[256];
} MUSHeader;


int main()
{
    MUSHeader h1, h2;
    FILE* ifp, *ofp;
    const char* fileName = "foo.bin";

    // napln strukturu
    h1.chans = 1;
    h1.freq = 2;
    h1.ssize = 3;
    h1.blck = 4;
    h1.resv = 5;
    h1.bla = 6;
    for (int i =0; i<256; ++i)
    {
        h1.amplt[i] = i;
    }

    // zapis do souboru
    ofp = fopen(fileName, "w");
    fwrite ( &h1, sizeof(MUSHeader), 1, ofp);
    fclose(ofp);

    // nacti ze souboru
    ifp = fopen(fileName, "r");
    fread(&h2, sizeof(MUSHeader), 1, ifp);

    // porovnej
    if (memcmp(&h1, &h2, sizeof(MUSHeader)) == 0)
    {
        printf("Shoduji se\r\n");
    }
    else
    {
        printf("Neshoduji se\r\n");
    }

    return 0;
}
Nahlásit jako SPAM
IP: 109.73.212.–
Ježíš zaplatil za naše hříchy a tím nás zachránil od věčné smrti a zatracení. Čtěte bibli, napravte se. Zde zdarma v češtině: http://bible21.cz/wp-content/uploads/2010/12/BIBLE21.pdf
Ovrscout
~ Anonymní uživatel
113 příspěvků
27. 3. 2015   #3
-
+1
-
Zajímavé

Nejjednodušší je vynutit/vypnout padding pro dannou strukturu..
např gcc:

#pragma pack(push,1)
typedef struct {
..
} MUSHeader;
#pragma pack(pop)

Pro různé překladače se zápis může mírně lišit.
Číslo v pack udává na kolik byte se zarovnává, 1=jeden byte tedy bez paddingu

Nahlásit jako SPAM
IP: 193.165.79.–
ondra.holub+1
Stálý člen
30. 3. 2015   #4
-
0
-

Zarovnání je dobrá poznámka, ale ještě to neřeší endianitu.

Samozřejmě záleží na tom, co v těch datech bude a co se s nimi bude dál dělat - pokud se např. jenom nějak přehází a zase se zapíšou do binární struktury nebo se nebudou zapisovat na jedné platformě a číst na jiné, tak se endianita moc řešit nemusí.

Nahlásit jako SPAM
IP: 131.207.242.–
Judegarek0
Newbie
30. 3. 2015   #5
-
0
-

Obecným řešením může být například Google Protocol Buffers.

https://developers.google.com/protocol-buffers/

Nahlásit jako SPAM
IP: 109.73.212.–
Ježíš zaplatil za naše hříchy a tím nás zachránil od věčné smrti a zatracení. Čtěte bibli, napravte se. Zde zdarma v češtině: http://bible21.cz/wp-content/uploads/2010/12/BIBLE21.pdf
Ovrscout
~ Anonymní uživatel
113 příspěvků
30. 3. 2015   #6
-
0
-

#4 ondra.holub
Tak endianita mi na mysl nepřišla, rep. tazatel se neptal  :)
To už pak řeším nějakou funkcí které předhodím ukazatel na strukturu a jednu položku po druhé překonvertuju.

Je to obecně nějaká taková fujky C ošklivost:
 

static void SwapByteOrder(unsigned char *d,int size)
{int i;
 unsigned char c;
 if (size<=1)return;
 for (i=0;i<size/2;i++)
  {
   c=d[i];
   d[i]=d[size-i-1];
   d[size-i-1]=c;
  }
  return;
}

#define Swap(A) SwapByteOrder((void*)(&A),sizeof(A))
//Swap struct
void SwapMUSHeader(MUSHeader *pData)
{
    _Static_assert(sizeof(*pData)==534);
        Swap(chans);
    Swap(pData->freq);
    Swap(pData->ssize);
    Swap(pData->blck);
    Swap(pData->resv);
    Swap(pData->bla);
    for (int i=0;i<sizeof(pData->amplt)/sizeof(pData->amplt[0]);i++)
    {
     Swap(pData->amplt[i]);
    }
    return;
}

#5 Judegarek
Myslím že původní dotaz je mířen na soubor s již existujícími daty v nějakém konkrétním formátu.
Předpokládám že data pocházejí z jiného programu který má pevný výstupní formát.
Po zběžném kouknutí myslím že protocolbuffers má vlastní vnitřní formát dat takže "Raw" data takto zpracovat nejdou.
Ale zatím jsem s ním ještě nepracoval, pokud na to je nějaký fígl,tak mne kdyžtak prosím opravte.

Nahlásit jako SPAM
IP: 193.165.79.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 13 hostů

Podobná vlákna

C# - webresponse - ustřihává hlavičky? — založil David Klouček

Hlavicky a ich funkcie — založil mORb

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý