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
Wie waere es mit 3 Dateien: eines für 32bit, eines für 16bit und eines für 1bit.
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.
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.
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.
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.
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.
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.
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 ...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.