Forum: Mikrocontroller und Digitale Elektronik Binärdaten sauber in Logdatei schreiben


von Heiko (Gast)


Lesenswert?

Hallo zusammen,

ich habe eine ganze Menge Daten, welche ich (mit einem STM32) auf eine 
SD-Karte logge. Es ist eine Mischung aus 32Bit, 16Bit und 1Bit Daten. 
Aktuell logge ich alle Daten als lesbare Zeichen. Da die Logfiles 
dadurch recht groß werden, wäre es sinnvoller die Daten direkt binär zu 
schreiben (spart Speicherplatz und das Ausgeben/Einlesen der Dateien 
wird schneller).
Mein Problem: Wie trenne ich die einzelnen Datensätze voneinander? Wenn 
ich davon ausginge, dass es niemals einen Schreibfehler geben kann, dann 
könnte ich natürlich von der bekannten Datensatzgröße ausgehen. Aber 
wenn ich das nicht garantieren kann, dann muss ich irgendein (oder 
mehrere) Trennzeichen haben, welches aber niemals in den Daten selber 
vorkommen kann.

Gibt es hierfür eine sinnvolle Lösung, ausser die Daten daraufhin zu 
überprüfen, dass nicht zufällig das gewählte Trennzeichen darin 
vorkommt?

Danke und Gruß, Heiko

von Mehmet K. (mkmk)


Lesenswert?

Wie waere es mit 3 Dateien: eines für 32bit, eines für 16bit und eines 
für 1bit.

von Nase (Gast)


Lesenswert?

Heiko schrieb:
> Da die Logfiles
> dadurch recht groß werden, wäre es sinnvoller die Daten direkt binär zu
> schreiben (spart Speicherplatz und das Ausgeben/Einlesen der Dateien
> wird schneller).
Ist das derzeit oder auf absehbare Zeit tatsächlich ein Problem für 
deine Anwendung? Nichts ist ätzender, als Log-/Konfigurationsdateien, 
die nur mit Spezialwerkzeug zu lesen sind...

Heiko schrieb:
> Gibt es hierfür eine sinnvolle Lösung, ausser die Daten daraufhin zu
> überprüfen, dass nicht zufällig das gewählte Trennzeichen darin
> vorkommt?
Jein. Sich Gedanken über das Format der Datensätze machen...
Geh mal anders ran an das Problem: Stell dir vor, es wäre keine 
Logdatei, sondern eine serielle Schnittstelle. Da würdest du dir 
sicherlich auch irgendein Datensatzformat ("Protokoll") ausdenken, bei 
dem du jederzeit den Anfang eines Satzes erkennst. Vermutlich würdest du 
noch eine Prüfsumme dranhängen.

Du musst dir halt einen Satztrenner aussuchen und diesen maskieren, 
falls er in den Nutzdaten vorkommt.

von Codix (Gast)


Lesenswert?

Da Du leider nicht geschrieben hast, in welcher Reihenfolge die Daten 
anfallen, kann ich Dir nur schreiben, wie ich das üblicher Weise mache.

Ich definiere meine Logdaten als struct (in C) und schreibe die Daten in 
dieser Größe binär sizeof(struct ....) auf die Platte.
Dadurch ist, solange die struct statisch ist, gewährleistet, dass immer 
die Satzgröße gleich ist.
Damit braucht man sich keine Satztrenner einfallen lassen und hat auch 
sonst
weniger Aufwand.
Lesen geht dann ebenso über die feste Satzlänge.
Wichtig dabei ist, dass man für beide Programme (Schreiben und Lesen) 
identische Compileroptionen setzt. Sonst geht das schief.

von Boris O. (bohnsorg) Benutzerseite


Lesenswert?

So ganz klar ist mir die Datenstruktur nicht, d.h. ob die verschieden 
breiten Wörter zusammengehören oder unabhängig voneinander geschrieben 
werden. Aber es gab in der alten Zeit sog. fixed length records. Ein 
Marker am Anfang bestimmt den Typ des Datensatzes und von da an ist die 
Wortbreite klar, bspw. könntest du die ASCII-Zeichen 1, 6 und 3 
verwenden, gefolgt von jeweils dem 1-, 16- bzw. 32-bit-Wort.

Wenn hingegen immer die drei Datentypen zusammengehören, wird es nicht 
besser als 7 Byte-Blöcken, da ich für das 1-bit-Wort auch ein Byte 
verwenden würde. So geht es immer in 7er Schritten voran. Wenn 
Speicherplatz keine Rolle spielt, würd' ich auf 8bit aufrunden und bspw. 
immer einen Zeilenumbruch oder etwas ähnlich praktisches (NUL…) als 
Trenner einsetzen.

von Jobst Q. (joquis)


Lesenswert?


von Peter M. (r2d3)


Lesenswert?

Heiko schrieb:
> Hallo zusammen,
>
> ich habe eine ganze Menge Daten, welche ich (mit einem STM32) auf eine
> SD-Karte logge. Es ist eine Mischung aus 32Bit, 16Bit und 1Bit Daten.

Du solltest vielleicht erläutern, ob Deine Datenmischung immer im selben 
Verhältnis ensteht (was die Struct-Lösung oben begünstigen würde), oder 
in beliebigen Mischverhältnissen.

von Sven B. (scummos)


Lesenswert?

Heiko schrieb:
> Mein Problem: Wie trenne ich die einzelnen Datensätze voneinander? Wenn
> ich davon ausginge, dass es niemals einen Schreibfehler geben kann, dann
> könnte ich natürlich von der bekannten Datensatzgröße ausgehen. Aber
> wenn ich das nicht garantieren kann, dann muss ich irgendein (oder
> mehrere) Trennzeichen haben, welches aber niemals in den Daten selber
> vorkommen kann.
>
> Gibt es hierfür eine sinnvolle Lösung, ausser die Daten daraufhin zu
> überprüfen, dass nicht zufällig das gewählte Trennzeichen darin
> vorkommt?

Die typische Lösung ist sowas wie 4 Byte "Synchronisationsmarker" im 
Datenstrom zu platzieren, die am Anfang eines Datensatzes stehen.

Die Wahrscheinlichkeit, dass in deinen Daten zufällig genau diese 4 Byte 
vorkommen ist verschwindend gering und selbst wenn es passiert, 
wiederholt die Synchronisationslogik die Suche nach dem Marker einfach 
für das nächste Paket noch einmal, sodass du nur ein Paket verlierst.

Also Idee ist, jedes Paket hat einen Marker am Anfang, und dann wird 
einfach kontinuierlich gelesen außer der Marker passt irgendwo nicht; in 
dem Fall ignorierst du einfach alle Daten bis zum nächsten Marker. Das 
ist sehr robust.

von A. S. (Gast)


Lesenswert?

Sven B. schrieb:
> Die Wahrscheinlichkeit, dass in deinen Daten zufällig genau diese 4 Byte
> vorkommen ist verschwindend gering und selbst wenn es passiert,
> wiederholt die Synchronisationslogik die Suche nach dem Marker einfach
> für das nächste Paket noch einmal, sodass du nur ein Paket verlierst.

Als erste Lösung gut, aber unsauber. Darum wird das "zufällige 
Verlieren" mit Byte-Stuffing (hier Long-Stuffing) auf 0 reduziert. Sagen 
wir die Magic-Marker-Number soll 128, dann definieren wir noch eine 
weitere (129) und ersetzten jedes "natürliche" Auftreten von 128 oder 
129 durch zwei Zeichen: 129, (Zeichen + 10).

Der Start-Marker ist damit weiterhin 128, und wenn 129 auftaucht, wird 
die 129 gelöscht und das nächste Zeichen -10 genommen.

von Sven B. (scummos)


Lesenswert?

Achim S. schrieb:
> Sven B. schrieb:
>> Die Wahrscheinlichkeit, dass in deinen Daten zufällig genau diese 4 Byte
>> vorkommen ist verschwindend gering und selbst wenn es passiert,
>> wiederholt die Synchronisationslogik die Suche nach dem Marker einfach
>> für das nächste Paket noch einmal, sodass du nur ein Paket verlierst.
>
> Als erste Lösung gut, aber unsauber. Darum wird das "zufällige
> Verlieren" mit Byte-Stuffing (hier Long-Stuffing) auf 0 reduziert. Sagen
> wir die Magic-Marker-Number soll 128, dann definieren wir noch eine
> weitere (129) und ersetzten jedes "natürliche" Auftreten von 128 oder
> 129 durch zwei Zeichen: 129, (Zeichen + 10).
>
> Der Start-Marker ist damit weiterhin 128, und wenn 129 auftaucht, wird
> die 129 gelöscht und das nächste Zeichen -10 genommen.

Hmja, ist nett, aber ist das wirklich nötig? Daten verlierst du eh nur 
dann wenn sowieso schon was fehlerhaft ist, und dann höchstens ein Paket 
mehr als beschädigt wurde ... mit einer typischerweise völlig 
verschwindenden Wahrscheinlichkeit bei 4 Byte Marker ...

von Mikro 7. (mikro77)


Lesenswert?

Heiko schrieb:
> dann muss ich irgendein (oder
> mehrere) Trennzeichen haben, welches aber niemals in den Daten selber
> vorkommen kann.

(1) Mit Endezeichen (bspw. irgendein Byte). Kommt das Endezeichen in den 
Daten vor, wird es dort doppelt geschrieben. Records werden als 
Bytesequenzen betrachtet und können unterschiedliche Länge haben.

(2) Bei ASCII benutzt du nur einen Teil des Zeichensatzes für die 
"Zahlen". Einen anderen Teil für Markierungen. Definierte dir deinen 
eigenen Zeichensatz, der dichtere Daten erlaubt (z.B. BCD, BASE64, 
etc.).

(3) Führe eine Checksum ein, die an das Ende des Records angehangen 
wird. (Damit sollte man schnell synchronisieren können.)

> ich habe eine ganze Menge Daten, welche ich (mit einem STM32) auf eine
> SD-Karte logge.

In einem Thread hier im Forum wurde kürzlich die (un)Eignung von SD 
Karten für zuverlässiges Speichern diskutiert.

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.