Forum: PC-Programmierung Datenformat interpretieren


von Zorro (Gast)


Lesenswert?

Ich habe ein Datenformat in der Form yyyy yyym mmmd dddd als 16 bit. 
Diese Zahl kriege ich als dezimal zahl. Wie kann ich es am sinvollsten 
so programmieren dass ich das Datum bekomme.

Mein vorschlag ich konvertiere in binär, und addiere z.B. die ersten 5 
Bitfelder das ergibt mein Datum. Ich müsste ja reisen Verschachtelungen 
machen mit case 1 an der Stelle 3 bedeutet Tag+=4 usw..

Aber ich glaube das geht schneller irgendwie oder?

von Zorro (Gast)


Lesenswert?

Zorro schrieb:
> das ergibt mein Datum

meine natürlich dass es meinen Tag vom Datum ergeben würde.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

In welcher Programmiersprache willst du das denn erledigen?

In C könnte man das (allerdings nicht portabel) tatsächlich mit einem 
Bitfeld erledigen:
1
const char *bitfield2date(uint16_t b)
2
{
3
   const unsigned year_offset = 1900; // ?
4
   union
5
   {
6
      uint16_t b;
7
      struct
8
      {
9
         uint16_t day: 5;
10
         uint16_t month: 4;
11
         uint16_t year: 7;
12
      }
13
      s;
14
   }
15
   u;
16
17
   u.b = b;
18
   char result[20];
19
   snprintf(result, sizeof(result), "%04d-%02d-%02d",
20
            u.s.year + year_offset, u.s.month, u.s.day);
21
   return result;
22
}

: Bearbeitet durch Moderator
von Zorro (Gast)


Lesenswert?

Jörg W. schrieb:
> In welcher Programmiersprache willst du das denn erledigen?

In Matlab.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Zorro schrieb:
> Jörg W. schrieb:
>> In welcher Programmiersprache willst du das denn erledigen?
>
> In Matlab.

Davon habe ich leider keine Ahnung, sorry.

Wird auf Bitmaskierung und -schieberei hinauslaufen.

C-Äquivalent:
1
const char *bitfield2date(uint16_t b)
2
{
3
   const unsigned year_offset = 1900; // ?
4
   unsigned int year, month, day;
5
6
   year = (b & 0xfe00) >> 9;
7
   month = (b & 0x01e0) >> 5;
8
   day = b & 0x001f;
9
   char result[20];
10
   snprintf(result, sizeof(result), "%04d-%02d-%02d",
11
            year + year_offset, month, day);
12
   return result;
13
}

: Bearbeitet durch Moderator
von Mani (Gast)


Lesenswert?

Jörg W. schrieb:
> Wird auf Bitmaskierung und -schieberei hinauslaufen.

Ist ja in C auch so. Nur dass das der Compiler übernimmt.

Zorro schrieb:
> Diese Zahl kriege ich als dezimal zahl. Wie kann ich es am sinvollsten
> so programmieren dass ich das Datum bekomme.

Ich hätte es durch maskieren und Division/schieben gemacht:
1
function [y,m,d] = getTime (x)
2
  a = uint16(x);
3
  y = (bitand(a,0xFE00)/2^9)+2000;
4
  m = (bitand(a,0x01E0)/2^5);
5
  d = bitand(a,0x001F);
6
end

Der Aufruf wäre dann z.B:
1
[y,m,d] = getTime(10036);
2
printf("%04d-%02d-%02d\n",y,m,d);

von Mani (Gast)


Lesenswert?

Sollte natürlich besser getDate heißen ;-P

von Zorro (Gast)


Lesenswert?

Vielen Danke euch! Habe allerdings eine zweite Kuriosität. In der 
Beschreibung steht der offset und dann was es sein sollte.

offset / byte: miliseconds
offset / byte: seconds
offset / byte: minute
offset / byte: houer

235475747 (somit sollten das die milisekunden sein an dem Die "Aufnahme" 
begann)
132319252 (sekunden)
4.2950e+09 (minuten)
3676 (und das die Stunden)


Allerdings komme ich hier auf keine vernünftigen Werte aus diesen 
Zahlen.

von Eric B. (beric)


Lesenswert?

Zorro schrieb:
> offset / byte: miliseconds
> offset / byte: seconds
> offset / byte: minute
> offset / byte: houer
1
function [h,m,s,u] = getTime (x)
2
  a = uint32(x);
3
  h = (bitand(a,0xFF000000)/2^24);
4
  m = (bitand(a,0x00FF0000)/2^16);
5
  s = (bitand(a,0x0000FF00)/2^8);
6
  u = (bitand(a,0x000000FF)/2^0);
7
end

von Dirk B. (dirkb2)


Lesenswert?

Zorro schrieb:
> Ich habe ein Datenformat in der Form yyyy yyym mmmd dddd als 16 bit.

Mit Division / und Modulo %

d = ymd % 32
m = (ymd / 32) % 16
y = ymd / 512

: Bearbeitet durch User
von Zorro (Gast)


Lesenswert?

Ich hatte es zwischenzeitlich schon gelöst, danke trotzdem an die 
letzten Posts.
Habe nun ein 4 Bytes langes Single als 32-bit Floating-Point. Kann ich 
das genauso behandeln da es ja auch gneauso lang (4Bytes) ist?

Also an dieser Adresse habe ich diesen Wert: 1.125209749000000e+09
Das soll die Framarate sein, die aber eigentlich 145Hz eingestellt war.

von Eric B. (beric)


Lesenswert?

Zorro schrieb:
> Habe nun ein 4 Bytes langes Single als 32-bit Floating-Point. Kann ich
> das genauso behandeln da es ja auch gneauso lang (4Bytes) ist?

Nein, weil das bestimmt kein Datum oder Uhrzeitangabe ist.

Zorro schrieb:
> Also an dieser Adresse habe ich diesen Wert: 1.125209749000000e+09
> Das soll die Framarate sein, die aber eigentlich 145Hz eingestellt war.

Dann hast du da ein Fehler.

: Bearbeitet durch User
von Zorro (Gast)


Lesenswert?

Eric B. schrieb:
> Dann hast du da ein Fehler.

In der Formatbeschreibung steht: Typ name: Single, Lenght(Byte):4Bytes, 
Data Type: 32 bit Floating-Point.

Wenn ich das nun so importiere: Iheader = fread(fileID,256,'uint32')

habe ich da den Wert: 1.125209749000000e+09.

Habe ich einen Denkfehler? Die anderen Werte wie das datum davor haben 
als data typ:32 bit unsigned Integer und Typ name: Dword und sind auch 4 
Bytes lang.

von Arno (Gast)


Lesenswert?

Zorro schrieb:
> Eric B. schrieb:
>> Dann hast du da ein Fehler.
>
> In der Formatbeschreibung steht: Typ name: Single, Lenght(Byte):4Bytes,
> Data Type: 32 bit Floating-Point.

32 bit Floating-Point...

> Wenn ich das nun so importiere: Iheader = fread(fileID,256,'uint32')

...und uint32...

> Habe ich einen Denkfehler?

...klingt zumindest, als passe es nicht zusammen ;)

MfG, Arno

von Udo S. (urschmitt)


Lesenswert?

Zorro schrieb:
> Ich habe ein Datenformat in der Form yyyy yyym mmmd dddd als 16 bit.
> Diese Zahl kriege ich als dezimal zahl.

Zorro schrieb:
> Habe nun ein 4 Bytes langes Single als 32-bit Floating-Point. Kann ich
> das genauso behandeln da es ja auch gneauso lang (4Bytes) ist?

Irgendwie schmeisst du hier allerlei Zahlenformate wild durcheinander.

Wie wäre es wenn du mal eine Beschreibung oder zumindest Beispiele 
(Binär bzw. Hex) lieferst, dann kann man dir vieleicht besser helfen.

: Bearbeitet durch User
von Zorro (Gast)


Lesenswert?

Also ich habe eine Beschreibung wie ein Header von dem Datenformat 
aufgebaut ist. darin habe ich ienmal eine Spalte mit dem Offset 
beginnend mit 0000 der Länge: das meiste ist DWORD lang.

Dann habe ich eine Tabelle die follgendes beinhaltet:

Typ name: ____ _ Length(Byte): __   Data Type:
byte _________ 1Byte _______________8 bit unsigned integer
word _________ 2 Bytes _____________uint16
dword____________4 Bytes_____________ uint32
Integer__________ 4 Bytes __________ uint32
Single __________ 4 Bytes __________ 32 bit Floating-Point

Nun ab ofssett 0000 bis offset:0084 ist alles Length: Dword.
Also importiere ich alles in Matlab mit dem Befehl: header = 
fread(fileID,256,'uint32').

Und habe in jeder Zeile dann eine DWORD-Lange Zahl also wie das datum 
wie ich es am Anfang im ersten Post beschrieben habe.

Jetzt kommt aber 4 Bytes weiter also im Offset:0088 Length SINGLE..

Aus der Tabelle geht ja hervor das der Typ Single ein 32 bit 
Floating-Point ist. Ich es aber alles ales uint32 importiere. Also was 
mache ich nun um diesesn werte vom typ Single(32 bit Floating-Point 
richtig zu importieren/interpretieren)

von Wolfgang (Gast)


Lesenswert?

Zorro schrieb:
> Aus der Tabelle geht ja hervor das der Typ Single ein 32 bit
> Floating-Point ist. Ich es aber alles ales uint32 importiere. Also was
> mache ich nun um diesesn werte vom typ Single(32 bit Floating-Point
> richtig zu importieren/interpretieren)

Ist überhaupt die Bytefolge dazu klar?

von Zorro (Gast)


Lesenswert?

Wolfgang schrieb:
> Ist überhaupt die Bytefolge dazu klar?

Also ab offset 0088 steht bei length:Single Description: FPS

Mehr ist nicht bekannt. Also ich weiss was zum Beispiel 4 bytes darunter 
steht bei offsett 0084 oder auch was dannach kommt bei offset 008c, was 
wiederum DWord-Lang ist.

Oder was genau wolltest du wissen?

von Zorro (Gast)


Lesenswert?

Also sonst steht da nichts in der Beschreibung was zum Beispiel im Byte 
1  steht..

von Dirk B. (dirkb2)


Lesenswert?

Zorro schrieb:
> Oder was genau wolltest du wissen?

Mach dich mal über Endianess schlau.

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Und du kannst mit dem IEEE-754 Fließkommaformat rumspielen: 
https://www.h-schmidt.net/FloatConverter/IEEE754de.html

von leo (Gast)


Lesenswert?

Zorro schrieb:
> header =
> fread(fileID,256,'uint32').

Warum liest du 256*4 Bytes als int, wenn ab Offset 84 ein 'single' 
kommt?

leo

von Zorro (Gast)


Lesenswert?

Also lese ich einfach bis einschließlich 84 uint32 und 088 lese ich als 
single ein? Und danach wieder als uint32. Ist das die Vorgehensweise?

von Zorro (Gast)


Lesenswert?

Allerdings weiss ich nicht wie ich fread sage dass er ab einer 
bestimmten Stelle der Datei lesen soll, also ab 88. Kennt ihr eine 
Möglichkeit?
Ginge es nicht einfach alles als uint32 einzulesen und den wert der 
Stelle 88 der eigentlich als single eingelesen werden muss zu 
konvertieren?

von Georg (Gast)


Lesenswert?

Zorro schrieb:
> Kennt ihr eine
> Möglichkeit?

fseek

Georg

von Zorro (Gast)


Lesenswert?

Danke! Also wenn ich einfach direkt von anfang an mit single einlsen 
habe ich an der stelle 88 den richtigen wert von 145 Dezimal. Lese ich 
aber zuerst die 34 werte mit uint32 und bewege den pointer auf den wert 
35 und lese dann als single ein wert ein kommt da 0 raus.

So:
A = fread(fileID,34,'uint32');
fseek(fileID,35,'bof')
fread(fileID,1,'single')

von Mathias A. (mrdelphi)


Lesenswert?

Lass das fseek mal weg...

...und, klappt's dann?

von Dirk B. (dirkb2)


Lesenswert?

Zorro schrieb:
> Lese ich
> aber zuerst die 34 werte mit uint32 und bewege den pointer auf den wert
> 35 und lese dann als single ein wert ein kommt da 0 raus.
>
> So:
> A = fread(fileID,34,'uint32');
> fseek(fileID,35,'bof')
> fread(fileID,1,'single')

Ein uint32 sind 4 Byte. Du musst also auf 35*4 positionieren.

Da du aber aus einem Eingabestrom liest, musst du nicht positionieren.
Der Lesezeiger wird automatisch weiter gestellt.

von Zorro (Gast)


Lesenswert?

Mathias A. schrieb:
> Lass das fseek mal weg...
>
> ...und, klappt's dann?

Dirk B. schrieb:
> Ein uint32 sind 4 Byte. Du musst also auf 35*4 positionieren.

Danke euch! klappt wunderbar. Und meine Idee alles als uint32 
einzulesen, und dann "umzuwandeln" ist überhaupt nicht möglich oder?

von Dirk B. (dirkb2)


Lesenswert?

Zorro schrieb:
> Danke euch! klappt wunderbar. Und meine Idee alles als uint32
> einzulesen, und dann "umzuwandeln" ist überhaupt nicht möglich oder?

Das ist ein Matlab Problem.

Edit:
Das geht mit typecast
https://www.mathworks.com/help/matlab/ref/typecast.html

: Bearbeitet durch User
von Zorro (Gast)


Lesenswert?

Habe es probiert mit typecast(x,'single')
x= 1.125209749000000e+09

kommem aber zwei werte Raus und nicht passende. Zuvor wurde x als uint32 
eingelesen.

von Zorro (Gast)


Lesenswert?

ein typecast(uint32(x),'single') schafft Abhilfe!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.