Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Dekodierer für Nachrichten (https://www.delphipraxis.net/173769-dekodierer-fuer-nachrichten.html)

benwen 15. Mär 2013 09:40

Dekodierer für Nachrichten
 
Verwendete Version: Delphi XE3

Hallo zusammen,

hoffe ich bekomme hier eine Antwort auf meine Frage:
Ich habe Nachrichten, die aus Paketen und Variablen bestehen und zu dekodieren sind. Die Paketinhalte (zusammengefasste Variablensequenznen) und Variablenlängen (z.B. Variablenlänge = 5 bit) sind spezifiziert. Alle Variablenwerte werden zunächst als Dezimalzahl interpretiert.

Momentane Vorgehensweise:
Bsp für Nachricht: 00101010101010101011110110....
1. Paket lesen
Variable 1 = 7bit: 0010101 -> 21
Variable 2 = 3 bit: 010 -> 2
usw.

Das funktioniert soweit ganz gut, aber da die Nachrichten deutlich länger sind als im dargestellten Beispiel und es Millionen von zu dekodierenden Nachrichten sind hätte ich gerne eine optimierte/schnellere Variante. Gibt es da eine in Delphi?
Allgemein finde ich die bisherige String-basierte Variante etwas unsauber/unschön. Was denkt ihr?

Bin für jeden Vorschlag dankbar!

Grüße !
benwen

p80286 15. Mär 2013 11:17

AW: Dekodierer für Nachrichten
 
Wie liegen Deine Nachrichten denn vor?
kommen da einzelne Bits vorbei oder werden wirklich Nullen und Einsen genutzt?
Im ersten Falle denke ich and Assembler und die entsprechenden Shift-Befehle, im zweiten würde ich einen BytetoBit-Übersetzer bauen.

Gruß
K-H

Aphton 15. Mär 2013 11:28

AW: Dekodierer für Nachrichten
 
Heißt das, die 01 Folge "00101010101010101011110110".. liegt als String vor? Warum zur Hölle macht man da eine Konvertierung in String? :|

Schau dir mal die logischen Operatoren an
and, or, not
und das Bitshifting:
shr, shl

Sollte ausreichen um zumindest ein GetBit() und SetBit() zu programmieren!

benwen 15. Mär 2013 12:10

AW: Dekodierer für Nachrichten
 
Ich bekomme die Nachricht als Bytestring, also z.B
Nachricht 1: a01b48768e9ff9
Nachricht 2: 46a57b8c94aa2332
...

Ich wandle jede Nachricht in einen Bitstring um und dann lese ich Variable für Variable aus dem Bitstring. Wie würde ich z.B. die ersten 12 bit auslesen bei Verwendung von Bitverschiebung? Nur ganz grob...

Merci!

BUG 15. Mär 2013 12:24

AW: Dekodierer für Nachrichten
 
Also ich würde mir als erstes etwas wie einen Bit-Stream Programmieren.

Delphi-Quellcode:
type BitReader = class
  contructor create(source: TStream);
  /** Gibt die nächsten amount Bits als Ganzzahl zurück. */
  function readBits(amount: byte): cardinal;
end;
An dieser Klasse lässt sich dann gut rumoptimieren ohne dein Programm durcheinander zu bringen.

Das mit dem Speichern von Bits als 01-Strings ist das unperformanteste was man machen kann. Nicht nur das String mindestens 8-mal so viel Speicher brauchen als das direkte Arbeiten mit Bits: Meisten Stringoperationen benutzen die Speicherverwaltung und die ist in fast allen Fällen langsam.

Aphton 15. Mär 2013 12:32

AW: Dekodierer für Nachrichten
 
Zitat:

Ich bekomme die Nachricht als Bytestring, also z.B
Nachricht 1: a01b48768e9ff9
Nachricht 2: 46a57b8c94aa2332
...
Nun da hast du wieder eine 200% Redundanz drinnen. Als Byte-Hex belegt man 2 Bytes für ein Byte an Daten. Dh die Zahlen 0..255 werden intern als 1 Byte abgespeichert, aber als HexString benötigt man 2 Zeichen, wo pro Zeichen ein Byte verwendet wird - also 2 Byte.

Ist also auch unfug!

Zur Frage mit 12 Bits.. Nun, die Daten liegen im Speicher vor.
Will man die ersten 12 Bits lesen, so liest man Bit 0 in (z.B.) x ein, shifted x um 1 nach links und wiederholt bis man an Bit 11 angelangt ist.

Du musst dir nur überlegen, wie du GetBit() & SetBit() realisiert. Alles andere ist klacks, weil es darauf dann aufbauen wird (soll!).

gammatester 15. Mär 2013 13:13

AW: Dekodierer für Nachrichten
 
Zitat:

Zitat von Aphton (Beitrag 1207550)
Zur Frage mit 12 Bits.. Nun, die Daten liegen im Speicher vor.
Will man die ersten 12 Bits lesen, so liest man Bit 0 in (z.B.) x ein, shifted x um 1 nach links und wiederholt bis man an Bit 11 angelangt ist.

Wie shiftet man den 11 mal ein Byte? :wink: Im Ernst: ein Klacks ist es erst dann, wenn auch die Bittigkeit (Endianness) geklärt ist.

Aphton 15. Mär 2013 14:34

AW: Dekodierer für Nachrichten
 
X muss ja nicht ein Byte sein

Edit: Nun gut, man muss natürlich immer in 8er Schritten gehen bis letztendlich die Anzahl <= 8 ist, wo man dann halt das shiften braucht.
Sonst kann man ja ganze Bytes nehmen!

Beispiel Pseudocode
Code:
ByteArray[0..3] = (255, 128, 0, 0) = (11111111, 10000000, 00000000, 00000000) // zB
pBytes = @ByteArray

Anzahl = 12
result = 0

while Anzahl > do
  Result = (Result shl 8) or pBytes^
  dec(Anzahl, 8)
  inc(pBytes)

while Anzahl > 0 do
  Result = (Result shl 1) or (pBytes^ and 1)
  dec(Anzahl)
Hier erhält man dann 111111111000b (4088d).
Anmerkung - diese Methode startet bei 0. Man müsste es so modifizieren, dass es auch mit nem anderen Offset klappt, ich will ihm aber die Arbeit nicht wegnehmen!

p80286 15. Mär 2013 14:55

AW: Dekodierer für Nachrichten
 
Zitat:

Zitat von gammatester (Beitrag 1207560)
: ein Klacks ist es erst dann, wenn auch die Bittigkeit (Endianness) geklärt ist.

Das ist ja wohl die Grundvorraussetzung.
Da Du irgendwann im Stream etwas Überhang haben wirst
0011 0101 0111 0000 1010 1110
Mußt Du beim Laden den vorderen und hinteren Überhang mit beachten. Wobei ich mich frage was ist mit führenden Nullen?
0 oder 0000 oder 00000000 ist als Wert immer Null.

Gruß
K-H

Phoenix 18. Mär 2013 06:58

AW: Dekodierer für Nachrichten
 
Also.. wir reden hier ja von unmanaged code, da kann man ja schweinereien machen :lol:

Ich würde erstmal versuchen, ein Struct (Packed Record) zu definieren, dass genau das gleiche Memory-Layout hat wie eine Nachricht.
Damit braucht man eigentlich nur noch einen Pointer auf den jeweiligen Nachrichtentyp auf den Beginn der Nachricht setzen, und kann dann schon sauber drauf zugreifen.

Das gibt natürlich einen Record pro Nachrichtentyp, aber der Zugriff ist dann ungeheuer bequem, und man muss nix umwandeln, umkopieren etc. Das heisst auch der Zugriff ist ziemlich flott.

Ich habe auf die Art mal einen Speicherbereich den ich aus einer SPS ausgelesen habe ausgewertet. War sehr schnell und sehr zuverlässig, solange sich das Layout der Nachrichten nicht verändert ;-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:34 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz