Rozbor dat z binárního proudu – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Rozbor dat z binárního proudu – C / C++ – Fórum – Programujte.comRozbor dat z binárního proudu – C / C++ – Fórum – Programujte.com

 

Lenny
~ Anonymní uživatel
14 příspěvků
5. 8. 2014   #1
-
0
-

Ahoj,

prosím o radu, jak vyřešit následující problém. Mám soubor, který otevřu pomocí fopen a chci přečíst data z binárního proudu. V "proudu" jsou pak obsaženy rámce, které mají strukturu jako na obrázku. Tzn. rámec je rozdělen na jednotlivé bity, přičemž počáteční byte rámce je vždy 0x9B (tzn. velikost 5 bitů).

Připojen obrázek.

Potřeboval bych data z rámců odfiltrovat, abych je následně mohl ukládat do nějaké struktury (a následně i zobrazit jejich číselnou podobu).

Předem děkuji za jakoukoliv pomoc.

Nahlásit jako SPAM
IP: 178.255.168.–
5. 8. 2014   #2
-
0
-

Asi číst po bytech a pomocí bitového posunu a bitového součinu získávat jednotlivé bity nebo sady bitů. 

hu

Nahlásit jako SPAM
IP: 193.86.81.–
Lenny
~ Anonymní uživatel
14 příspěvků
5. 8. 2014   #3
-
0
-

Děkuji za radu.

Bitový posun a součin chápu, ale nevím, jak zprostředkovat to čtení po bytech. Resp. čtení tak, abych vždy přečetl jen jeden rámec, pak druhý atd, dle té signalizace počátku 0x9B.

Nahlásit jako SPAM
IP: 178.255.168.–
JoDiK
~ Anonymní uživatel
987 příspěvků
5. 8. 2014   #4
-
0
-

#3 Lenny
Udělej mi jasno v tom, jak je to organizováno. Z toho cos napsal jsem zmaten. Rámec je jak píšeš rozdělen na bity ale pak najednou říkáš něco o počátečním bajtu rámce a že jeho hodnota znamená  5 bitů???

Takže jak to teda je?

1 celý rámec zabírá kolik bajtů/bitů? Je tato velikost konstantní?

Pak se můžem pohnout...

Nahlásit jako SPAM
IP: 88.100.43.–
Lenny
~ Anonymní uživatel
14 příspěvků
5. 8. 2014   #5
-
0
-

#4 JoDiK
Mám binární proud, v němž jsou obsaženy jednotlivé rámce (ale např. rámec_1 nemusí být hned navázán rámcem_2). Každý tento rámec má pak vždy stejnou strukturu (předchozí obrázek). Prvních pět bitů reprezentuje tzv. identifikátor. Ten slouží k rozpoznání počátku rámce a má trvalý byte 0x9B. Následuje dalších 9 bitů atd (opět každý tento blok bitů reprezentuje nějakou věc).

Abych odpověděl na otázku, zda je velikost rámce konstantní - ne není. Ve skutečnosti vypadá rámec takhle:

Připojen obrázek.


Tzn. vzhledem k poslednímu bloku v rámci DATA, není velikost celého rámce předem známá.

Nahlásit jako SPAM
IP: 178.255.168.–
KIIV
~ Moderátor
+43
God of flame
5. 8. 2014   #6
-
0
-

mimochodem, jak se ti vlastne dokazalo narvat 0x9B na 5 bitu? vzdyt je to binarne 0b10011011

co vubec resis za protokol?

Nahlásit jako SPAM
IP: 94.113.95.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Lenny
~ Anonymní uživatel
14 příspěvků
5. 8. 2014   #7
-
0
-

Moc se omlouvám, má tam být 8 bitů. Špatně jsem se podíval.

Co řeším za protokol? - moc nerozumím otázce... prostě chci z binárního proudu "dešifrovat" informace a vypsat je na obrazovku

Nahlásit jako SPAM
IP: 178.255.168.–
JoDiK
~ Anonymní uživatel
987 příspěvků
5. 8. 2014   #8
-
0
-

#7 Lenny
Nechceš se podívat ještě jednou, jestli ty infobity nedávají v součtu počet dělitelný osmi? Tím by se to dost zjednodušilo...

Nahlásit jako SPAM
IP: 88.100.43.–
Lenny
~ Anonymní uživatel
14 příspěvků
5. 8. 2014   #9
-
0
-

Znova se omlouvám, ty bity u bloků jsem psal jen orientačně. Nevěděl jsem, že to má pro obecný řešení nějakou váhu. Takže ještě jednou a teď už přesně dle skutečnosti:

Připojen obrázek.


Takže dělitelné osmi to je.

Nahlásit jako SPAM
IP: 178.255.168.–
JoDiK
~ Anonymní uživatel
987 příspěvků
5. 8. 2014   #10
-
0
-

#9 Lenny
No sláva, tak ještě doplň jestli i data jsou de fakto v bajtech (celkový počet bitů je dělitelný osmi), přičemž délka dat je jak předpokládám samozřejmě jedna z položek info bloku (hlavičky) a pak už není co řešit. Prostě přečti daný počet bajtů tvořících hlavičku, děkóduj pomocí bitových operací potřebné informace (především délku dat) a pak přečti daný počet bajtů dat do nějakého bufferu. Data pak zpracuj...

Pokud tam délka dat není, ale délka dat je dělitelná osmi a hodnota 9B v datech nemůže být obsažena, pak čti data po bajtech do bufferu tak dlouho, dokud nenarazíš na 9B...

Nahlásit jako SPAM
IP: 88.100.43.–
Lenny
~ Anonymní uživatel
14 příspěvků
5. 8. 2014   #11
-
0
-

#10 JoDiK
Ano, délku dat reprezentuje jeden z infobloků, přičemž samotná data jsou pak v bytech.

Jinak děkuji za radu, teoreticky to chápu. Prakticky však nevím jak zrealizovat to přečtení hlavičky. Resp. jak dostat nějakou konkrétní hodnotu, od které bych se již mohl posouvat přes jednotlivé infobloky (prostřednictvím bitových operací). Chápu správně, že budu muset použít konstrukci s fseek?

Nahlásit jako SPAM
IP: 178.255.168.–
JoDiK
~ Anonymní uživatel
987 příspěvků
6. 8. 2014   #12
-
0
-

#11 Lenny
Předpokládám, že v C nevymysleli nějaké nové hranaté kolo a čtení ze souboru funguje "normálně", tzn, že fseek potřebuješ jen kdy chceš v souboru při čtení přeskakovat. Pokud ale chceš kontinuálně přečíst všechny údaje v souboru od začátku, o automatické posouvání v souboru je postaráno.

Přečtení hlavičky zrealizuj tak, že přečteš do nějakého bufferu všechny bajty hlavičky.

Předpokládám, že po otevření souboru hned první údaj v něm je hlavička. Takže rovnou čti například (pokud jsem to dobře spočítal, hlavička má 9 bajtů)

fread(buffer, 1, 9, f)
 

v bufferu tak budeš mít všechny bajty hlavičky - pokud ten buffer bude pole bajtů, v prvním máš hodnotu 9B, z druhého si bitovým posunem o 1 doprava vezmeš těch 7 bitů první údaj, bitovým součinem s 1 získáš hodnotu toho posledního bitu atd...

Ze třetího bajtu těch prvních pět bitů získáš zase bitovým posunem o tři doprava, zbývající tři bity získáš bitovým součinem s 7. Ten si uložíš do proměnné 32bit. Posuneš ji o tři bity doleva a bitově do ní přičteš hodnotu dalšího bajtu z bufferu, zase posuneš o osm bitů doleva, přičteš další atd atd.

Až zjistíš velikost dat, tak je přečteš, tím se automaticky přesune ukazatel v souboru na začátek další hlavičky a můžeš rovnou aplikovat předchozí postup.

Poud bys ale po otevření souboru chtěl přeskočit třeba na sedmý blok, to už tak snadné nebude a protože délka dat je proměnná, nelze rovnou skákat fseek. Pokud v hlavičce není uloženo nějaké pořadové číslo, nepůjde použít ani postupné přibližování, takže prostě budeš muset přečíst první hlavičku a fseek přeskočit data na začátek druhé hlavičky, tu přečíst a zase přeskočit až na tu sedmou...

Nahlásit jako SPAM
IP: 88.103.236.–
JoDiK
~ Anonymní uživatel
987 příspěvků
6. 8. 2014   #13
-
0
-

#12 JoDiK
Ještě jednou jsem si přečetl tvůj upřesňující dotaz a možná potřebuješ pochopit především toto:

Při čtení ze souboru žádně hodnoty zvlášť po bitech nezjistíš, ze souboru lze číst nejmenší velikost 1 bajt. Takže si to načteš do paměti po bajtech do nějakého bufferu (proměnné) a s tou už si budeš provádět jakékoliv bitové či jiné operace...

Nahlásit jako SPAM
IP: 88.103.236.–
Lenny
~ Anonymní uživatel
14 příspěvků
6. 8. 2014   #14
-
0
-

#13 JoDiK
Tak mám napsáno otevření binárního proudu, uložení do bufferu a zavření. Tzn. mám nějaký:

char * buffer;

Teď bych tedy potřeboval rozebrat ty jednotlivé infobity. Buffer chápu, že obsahuje nějaký bity 011011... tzn. nejdříve posunu do leva o 8, čímž přeskočím tu hlavičku. Další posloupnost bitů budu ukládat do zvláštích polí (či struktury). Problém je, že na char nemůžu použít bitový posuny.

jak mám chápat to pole bajtů? To je přímo datový typ v C?

Nahlásit jako SPAM
IP: 178.255.168.–
6. 8. 2014   #15
-
0
-

 na char nemůžu použít bitový posuny.

  na takový nesmysl jsi přišel kde?

Máš pole typu char. První byte (tj prvek pole) je prvních 8 bitů, druhý byte je dalších 8 bitů, které podle tvého diagramu potřebuješ rozdělit na 7 bitů a 1 bit. těch 7 bitů získáš bitovým posunem vpravo, vznikne byte ve kterém na pozici MSB bude 0 následovaná požadovanou sedmicí bitů.1 bit se nachází na pozici LSB a lze ho získat bitovým součinem s konstantou 0x01.  Ze třetího bytu tě zajímá nejdříve prvních 5 bitů, použiješ opět bitový posun vpravo.... 

Zjednodušeně: projdeš pole bytů a jednotlivé byty rozdělíš na skupiny bitů podle diagramu, který jsi sem dal.

hu

Nahlásit jako SPAM
IP: 193.86.81.–
JoDiK
~ Anonymní uživatel
987 příspěvků
6. 8. 2014   #16
-
0
-

#14 Lenny
pole bajtů je pole bajtů, v céčku nedělám, ale pochybuju, že by neumožňovalo deklarovat cokoliv.

nehledě na to, že taky lze cokoliv přetypovat na cokoliv...

Jak tak chvíli googluju, tak standardní C nemá typ byte, jen char, ale jak se zdá, má přesně to co potřebuješ - bitové pole, kde si nadefinuješ počty bitů jednotlivých částí té tvé hlavičky:

http://www.builder.cz/rubriky/c/c--/ucime-se-c-25-dil-bitove-operatory-a-bitove-pole-155778cz

Nahlásit jako SPAM
IP: 88.100.43.–
Lenny
~ Anonymní uživatel
14 příspěvků
6. 8. 2014   #17
-
0
-

#15 hlucheucho
Získání těch prvních 7 bitů chápu.

struct->infoblock_1 = buffer[1] >> 1;


Ale získání toho 1 bitu prostřednictvím součinu s konstantou 0x01 nemůžu pochopit. Když např. 1001 & 1 = 1001, tzn. získám stejný výsledek... vím že je to asi myšleno jinak, ale nemůžu tomu přijít na kloub..

Nahlásit jako SPAM
IP: 178.255.168.–
6. 8. 2014   #18
-
0
-

napiš si tu jedničku dvojkově, pak bude vypadat třeba takto 0001. Takže 1001 & 0001 = ?

hu

Nahlásit jako SPAM
IP: 193.86.81.–
Lenny
~ Anonymní uživatel
14 příspěvků
6. 8. 2014   #19
-
0
-

#18 hlucheucho
Jasný, chápu.

Tak to rozdělení do infobloků mi už funguje- děkuji. Teď ale řeším další problém.

Otevřu soubor a všechen binární proud překopíruju do proměnné buffer. Z ní pak umím pro první rámec provést rozdělení do infobloků. Ovšem já takhle potřebuju projet všechny rámce (přičemž ale vím, že rámce na sebe nemusí hned navazovat). Tzn. potřebuji aby mi nějaký cyklus vždy zachytil hlavičku rámce (0x9B). Cyklus je mi jasný, ale nevím, jak udělat to zachytávání?

Nahlásit jako SPAM
IP: 178.255.168.–
Lenny
~ Anonymní uživatel
14 příspěvků
7. 8. 2014   #20
-
0
-

#19 Lenny
Tak zachycování hlavičky už mám, ale vzhledem k chybným výpisum infobloků jsem zjistil, že mám chybu u jedné mé operace (zdroják níže) s bitovým posunem a součinem. Potřebuji sloučit více bitů. To co používám níže funguje jen na některé bitové posloupnosti.. což vůbec nechápu.. na papíře mi to přitom "funguje"

unsigned char array [4];

array[0] = 0xD8;
array[1] = 0x55;
array[2] = 0xA1;
array[3] = 0xB2;

struct = (((pole[0] & 0xFFFFFFFF) << 24) | ((pole[1] & 0xFFFFFF) << 16) | ((pole[2] & 0xFFFF) << 8) | pole[3]);

Zjednodušeně: Potřebuji aby v struct bylo D855A1B2, tzn. 11011000 00110111 10100001 10110010

Děkuji za případné rady.

Nahlásit jako SPAM
IP: 178.255.168.–
KIIV
~ Moderátor
+43
God of flame
7. 8. 2014   #21
-
0
-

zaprve to muzes udelat klidne i pomoci  *((unsigned int *)&struktura) = 0xD8<<24 | 0x55<<16 | 0xA1 << 8 | 0xB2;

problem je akorat v tom, ze jsi s vysokou pravdepodobnosti na systemu s little endian, takze toto udela presne opacne poradi a musel bys pouzit treba *((unsigned int *)&struktura) = htonl(...);

a nebo ultimatne:

 

unsigned char * tmp = (unsigned char *) struktura;
tmp[0] = 0xD8;
tmp[1] = 0x55;
tmp[2] = 0xA1;
tmp[3] = 0xB2;

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Lenny
~ Anonymní uživatel
14 příspěvků
7. 8. 2014   #22
-
0
-

#21 KIIV
Zkusil jsem použít to ultimátní řešení, ale program ten zápis asi nevstřebá - při spuštění spadne (použil jsem přímo ten zdroják).

Chápu správně, že tim jenom přetypuju strukturu na unsigned char (jedná se jinak o unsigned int info : 32)?

Nahlásit jako SPAM
IP: 178.255.168.–
KIIV
~ Moderátor
+43
God of flame
7. 8. 2014   #23
-
0
-

#22 Lenny
jo mam tam chybu  --  (unsigned char *) &struktura;  v prvni ukazce to nebylo

ale furt musis pocitat s tim byteorderem - hlavne u vypisu a tak

+ int nemusi byt vzdy 32b .. jistejsi je pouzit  uint32_t  a nemusis specifikovat : 32

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Lenny
~ Anonymní uživatel
14 příspěvků
7. 8. 2014   #24
-
0
-

#23 KIIV
Chápu tedy správně, že to má vypadat takhle?

unsigned char * array = (unsigned char *) & ramec.infoblok_3;

array[0] = 0xAA;
array[1] = 0xD8;
array[2] = 0x55;
array[3] = 0x00;
array[4] = 0x00;

Při kompilaci mi to ale hází error - cannot take address of bit-field 'infoblok_3'

Jinak jak je myšlen ten problém s byteorderem? Asi jsem to nepochopil.

Nahlásit jako SPAM
IP: 178.255.168.–
KIIV
~ Moderátor
+43
God of flame
7. 8. 2014   #25
-
0
-
Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Lenny
~ Anonymní uživatel
14 příspěvků
7. 8. 2014   #26
-
0
-

No já mám takhle udělanou celou tu strukturu, např.

unsigned int info1 : 32

unsigned int info2 : 1

unsigned int info3 : 7

Je to tak dle velikosti infoblokuv bitech. Mám chápat tu alternativu s uint jako:

uint32_t info; // ale pokud to mám chápat jako datový typ, tak ho C nezná..

Nahlásit jako SPAM
IP: 178.255.168.–
KIIV
~ Moderátor
+43
God of flame
7. 8. 2014   #27
-
0
-

#26 Lenny
#include <stdint.h> 

sem tajne doufal, ze to zvladnes vygooglit :)

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Lenny
~ Anonymní uživatel
14 příspěvků
7. 8. 2014   #28
-
0
-

#27 KIIV
Tak nevim, ted to mam takhle:

typedef struct struktura{  uint32_t infoblok; ...
.
.
.
unsigned char * array = (unsigned char *) &ramec.infoblok;
array[0] = 0xAA;
array[1] = 0xD8;
array[2] = 0x55;
array[3] = 0x00;
array[4] = 0x00;


ramec.infoblok = (((array[0] & 0xFFFFFFFF) << 24) | ((array[1] & 0xFFFFFF) << 16) | ((array[2] & 0xFFFF) << 8) | array[3]);

Ale když nechám vypsat ramec.infoblok, tak se mi zobrazí -665518080, což binárně tozhodně není to, co má být...

Nahlásit jako SPAM
IP: 178.255.168.–
KIIV
~ Moderátor
+43
God of flame
7. 8. 2014   #29
-
0
-

ja spis nechapu co to furt prepisujes nekolikrat...

nejdriv to prepises tim array[0] = ...  a pak to prepises znova pomoci bitovejch posunu (a jeste k tomu v opacnem poradi bajtu)...

a vypisujes zaprve se znamenkem, zadruhe v jinem byteorderu (kterej tu uz zminuju po desate)

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
KIIV
~ Moderátor
+43
God of flame
7. 8. 2014   #30
-
0
-

#28 Lenny
neni nad to si to taky vypsat:

#include <stdio.h>
#include <stdint.h>

typedef struct struktura{  uint32_t infoblok; } TStruktura;


int main() {
  TStruktura ramec;

  unsigned char * array = (unsigned char *) &ramec.infoblok;
  array[0] = 0xAA;
  array[1] = 0xD8;
  array[2] = 0x55;
  array[3] = 0x00;

  printf("0x%08X\n",ramec.infoblok);

  ramec.infoblok = (((array[0] & 0xFFFFFFFF) << 24) | ((array[1] & 0xFFFFFF) << 16) | ((array[2] & 0xFFFF) << 8) | array[3]);

  printf("0x%08X\n",ramec.infoblok);

  return 0;
}

A ted je to nejdulezitejsi:   v pameti je to v opacnem poradi ... LSB je na pozici 0 ne na pozici 3!   ale normalne se to na siti predpoklada v opacnem poradi.. jako ze prvni jde bajt s nejvyssi vahou (MSB)

vysledek je mimochodem:

0x0055D8AA
0xAAD85500 (ale v pameti je to 0x00 0x55 0xD8 0xAA !!!!!)

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
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, 54 hostů

Podobná vlákna

Rozbor kodu — založil shockwave

Rozbor kodu, for loop — založil shockwave

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ý