Comment compresser des chaînes ASCII en moins d'octets?


12

Je travaille avec un appareil intégré avec un protocole unique qui envoie des messages à d'autres appareils et je crée une application qui analyse les paquets envoyés. Chaque paquet contient 8 octets. Le protocole est défini comme où le premier octet est l'en-tête et les 7 octets restants sont les données.

Ils essaient de passer une chaîne d'ID particulière, mais la chaîne d'ID comporte 8 caractères (ASCII), elle ne tient donc pas sur 7 octets.

Ce que mon collègue m'a dit, c'est qu'ils vont transformer les 8 octets ascii de la chaîne d'origine en entier (décimal) et m'en envoyer 4 octets. Ils m'ont dit que je devrais pouvoir obtenir la chaîne d'origine à partir des 4 octets. J'ai du mal à m'enrouler la tête là-dessus.

Donc, si vous avez une chaîne d'identification comme "IO123456", c'est 0x49 0x4f 0x31 0x32 0x33 0x34 0x35 0x36 en ASCII. Comment diable pouvez-vous compresser cela en 4 octets en le transformant en un entier et je peux en obtenir la chaîne d'origine ? Suis-je en train de manquer quelque chose ou mon collègue se trompe-t-il? Je comprends que c'est une question vraiment bizarre, mais cela n'a vraiment aucun sens pour moi.


1
Chaque caractère ASCII ne prend que 7 bits, donc une chaîne de 8 caractères ASCII peut en effet être stockée en 8 * 7 bits - 7 octets.
luiscubal

Réponses:


17

L'ID est-il toujours sous la forme: IO123456? Ce que votre collègue pourrait signifier, c'est qu'il n'envoie que la partie numérique, qui tient facilement dans 4 octets en omettant la partie "IO".


1
C'était ça. Les deux premiers octets sont toujours en lettres et les autres sont en chiffres, il pourrait donc facilement tenir en 4 octets comme vous l'avez dit. Bien que je ne sache pas d'où vient le nombre arbitraire de 4 octets, parce que 999999 en hexadécimal est F423F donc c'est 3 octets tout au plus ..
l46kok

5
@ l46kok: les entiers sur 3 octets (24 bits) sont très rares, il est donc probablement plus facile pour eux de l'envoyer en tant qu'entier sur 32 bits (4 octets). Je ne serais pas complètement surpris si vous l'obteniez dans la représentation native (ordre des octets) du périphérique intégré.
Bart van Ingen Schenau

16

Si les deux premiers caractères ne sont pas constants (mais sont toujours des lettres) et les six caractères restants sont toujours des nombres, une chaîne comme "IO123456" peut être compressée en 5 octets en convertissant les nombres au format décimal codé binaire (BCD):

IO123456 -> 0x49 0x4f 0x31 0x32 0x33 0x34 0x35 0x36
             |    |      \   /     \   /     \   /
            0x49 0x4f     0x12      0x34      0x56

S'il existe un ensemble limité d'identifiants possibles (les deux premières lettres), vous pouvez les coder en un nombre et l'envoyer à la place (tant qu'il n'y a pas plus de 256 combinaisons), par exemple:

IO -> 0x00
RD -> 0x01
WT -> 0x02
   ...
AB -> 0x10
   ...
ZZ -> 0xff

afin que la chaîne d'origine soit compressée en 4 octets sans aucune perte d'information:

IO123456 -> 0x49 0x4f 0x31 0x32 0x33 0x34 0x35 0x36
              \    /     \   /     \   /     \   /
               0x00       0x12      0x34      0x56

Bien sûr, ce processus peut également être inversé pour obtenir la chaîne d'identification d'origine.


3

Si la chaîne peut être n'importe quelle séquence de caractères:

  • Si vous pouvez être sûr que vos chaînes n'utilisent pas le bit le plus significatif de chaque octet, vous pouvez les découper en sept bits et utiliser des opérations au niveau du bit pour décaler les 56 bits restants dans les 56 bits dont vous disposez.

  • Si les chaînes ne sont que des lettres et des chiffres, proposez une représentation sur 6 bits de cet ensemble et créez une chaîne de 48 bits de votre identifiant.

Si le format est toujours composé de deux lettres suivies d'une chaîne de chiffres:

  • Laissez les deux premiers octets seuls et encodez le nombre en un entier de six octets. IO123456devient 0x49 0x4f 0x01E240.

  • Laissez les deux premiers octets seuls et compressez les chiffres en décimal codé en binaire . IO123456devient 0x49 0x4f 0x12 0x34 0x56.


1

Du point de vue de la question affichée ici, il pointe vers un protocole industriel appelé HART. Ce protocole a une façon unique d'envelopper les caractères ASCII. Il est appelé Packed-ASCII. Mais il n'emballe pas les 8 caractères à 4! Selon Packed-ASCII, les 8 octets ASCII sont convertis en 6. 4 en 3 et ainsi de suite.

Dans ce protocole, la longueur des paramètres d'une certaine requête est toujours fixe. Les personnages restants doivent donc être complétés par des personnages de l'espace. Pourtant, tout cela est spécifique à HART. Si vous confirmez que vous travaillez là-dessus, je mettrai la procédure exacte d'emballage et de déballage.


0

Peut-être en convertissant '0123456' en un entier long.

Mais cela ne fonctionnerait que pour les identifiants numériques.

Un autre schéma possible serait de convertir votre codage ECMA-1 7 à 6 bits qui vous donnerait une chaîne de six octets mais vous seriez limité au jeu de caractères en chiffres lettres majuscules et à un jeu limité de caractères de ponctuation.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.