Як ви стискаєте рядки ASCII в меншу кількість байтів?


12

Я працюю з вбудованим пристроєм з унікальним протоколом, який надсилає повідомлення на інші пристрої, і я роблю програму, яка аналізує надіслані пакети. Кожен пакет містить 8 байт. Протокол визначається так, як перший байт - заголовок, а решта - 7 байт.

Вони намагаються передати певний рядок ідентифікатора, але ID для нього - 8 символів (ASCII), тому він не вміститься в 7 байт.

Що сказав мій колега, це те, що вони збираються перетворити 8 байтів Ascii початкового рядка в ціле число (десятковий) і надіслати мені 4 байти. Вони сказали мені, що я повинен мати можливість отримати оригінальний рядок із 4-х байт. Мені важко обернути голову з цього приводу.

Отже, якщо у вас є рядок ідентифікатора типу "IO123456", це 0x49 0x4f 0x31 0x32 0x33 0x34 0x35 0x36 в ASCII .. Як на землі ви можете стиснути це в 4 байти, перетворивши його в ціле число, і я можу отримати з нього вихідний рядок ? Я щось пропускаю, або мій колега помиляється? Я розумію, це справді химерне питання, але це серйозно не має для мене сенсу.


1
Кожен символ ASCII займає лише 7 біт, тому рядок з 8 символами ASCII дійсно може зберігатися в 8 * 7 біт - 7 байт.
luiscubal

Відповіді:


17

Чи ідентифікатор завжди у формі: IO123456? Що може означати ваш колега, це те, що він надсилає лише числову частину, яка легко вписується в 4 байти, опускаючи частину "IO".


1
Це було все. Перші два байти завжди буквою, а решта - цифрами, так що він міг легко вміститися в 4 байти, як ви сказали. Хоча я не знаю, звідки взялося довільне число 4 байтів, тому що 999999 у шестигранному є F423F, тож це найбільше 3 байти ..
l46kok

5
@ l46kok: 3-байтові (24-бітні) цілі числа дуже рідкісні, тому їм, ймовірно, простіше надіслати його як 32-бітове (4-байтове) ціле число. Я не був би зовсім здивований, якби ви отримали це в натурному поданні (порядку байтів) вбудованого пристрою.
Барт ван Інген Шенау

16

Якщо перші два символи не є постійними (але це завжди букви), а решта шість символів - це завжди цифри, рядок типу "IO123456" можна упакувати в 5 байтів шляхом перетворення чисел у двійкові кодовані десяткові (BCD) формати:

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

Якщо є обмежений набір можливих ідентифікаторів (перші дві літери), ви можете закодувати їх у число і надіслати його замість цього (доки не буде більше 256 комбінацій), наприклад:

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

так що початковий рядок упаковується в 4 байти без втрати інформації:

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

Звичайно, цей процес також можна змінити, щоб отримати початковий рядок ідентифікатора.


3

Якщо рядком може бути будь-яка послідовність символів:

  • Якщо ви можете бути впевнені, що ваші рядки не використовують найважливіший біт у кожному байті, ви можете порубати кожен до семи біт і використовувати побітові операції для переміщення решти 56 біт на 56 біт, які у вас є.

  • Якщо рядки - це лише літери та цифри, придумайте 6-бітове представлення саме цього набору та зробіть 48-бітну рядок свого ідентифікатора.

Якщо формат - це завжди дві літери, після яких слід рядок цифр:

  • Перші два байти залиште в спокої і закодуйте число в шестибайтове число. IO123456стає 0x49 0x4f 0x01E240.

  • Перші два байти залиште в спокої і запакуйте цифри як двійкові кодовані десяткові . IO123456стає 0x49 0x4f 0x12 0x34 0x56.


1

З контексту поставленого тут питання вказує на деякий промисловий протокол під назвою HART. Цей протокол має унікальний спосіб загортання символів ASCII. Це називається Packed-ASCII. Але все-таки він не пакує 8 символів до 4! Згідно з Packed-ASCII, 8 байт ASCII перетворюються на 6. 4 - 3 тощо.

У цьому протоколі завжди встановлюється довжина параметрів у певному запиті. Тож решта символів потрібно замістити пробілами. Але все це специфічно для HART. Якщо ви підтвердите, що працюєте над цим, я поставлю точну процедуру упаковки та розпакування.


0

Можливо, перетворивши '0123456' у довге ціле число.

Але це буде працювати лише для числових ідентифікаторів.

Іншою можливою схемою було б перетворення 7 - 6-бітового кодування ECMA-1, яке дасть вам шість байтових рядків, але ви будете обмежені набором символів з великої літери і обмеженим набором знаків пунктуації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.