US-ASCII строка (де) сжатие в / из байтового массива (7 бит / символ) - PullRequest
1 голос
/ 04 июля 2019

Как все мы знаем, ASCII использует 7-битный код для кодирования символов, поэтому число байтов, используемых для представления текста, всегда меньше длины текстовых букв

Например:

    StringBuilder text = new StringBuilder();
    IntStream.range(0, 160).forEach(x -> text.append("a")); // generate 160 text
    int letters = text.length();
    int bytes = text.toString().getBytes(StandardCharsets.US_ASCII).length;
    System.out.println(letters); // expected  160,  actual 160
    System.out.println(bytes); //   expected  140,  actual 160

Всегда letters = bytes, но ожидается letters> bytes.

основной прототип: в smpp протоколе sms тело должно быть <= 140 байт, если мы использовали ascii кодировку, то вы можете написать 160 букв =(140*8/7), так Я хотел бы, чтобы текст, закодированный в 7-bit based ascii, мы используем JSMPP библиотека

Может кто-нибудь объяснить мне, пожалуйста, и направить меня на правильный путь, спасибо заранее (:

Ответы [ 4 ]

2 голосов
/ 04 июля 2019

(160 * 7-160 * 8) / 8 = 20, поэтому вы ожидаете, что к концу вашего скрипта будет использовано на 20 байтов меньше. Тем не менее, существует минимальный размер для регистров, поэтому, даже если вы не используете все свои биты, вы все равно не можете соединить его с другим значением, поэтому вы все еще используете 8-битные байты для своих кодов ASCII, поэтому Вы получаете тот же номер. Например, строчная буква «а» равна 97 в ASCII

‭01100001‬

Обратите внимание, что ведущий ноль все еще там, даже если он не используется. Вы не можете просто использовать его для хранения части другого значения.

Иными словами, в чистых ASCII-письмах всегда должны быть равны байты.

(Или представьте, что объект размера 7 помещается в блоки размера 8. Нельзя разбивать объекты на части, поэтому количество блоков должно равняться количеству объектов - по крайней мере, в этом случае.)

1 голос
/ 05 июля 2019

Вот быстрое и грязное решение без каких-либо библиотек, то есть только встроенные средства JRE. Он не оптимизирован для эффективности и не проверяет, действительно ли сообщение является US-ASCII, он просто принимает его. Это просто подтверждение концепции:

package de.scrum_master.stackoverflow;

import java.util.BitSet;

public class ASCIIConverter {
  public byte[] compress(String message) {
    BitSet bits = new BitSet(message.length() * 7);
    int currentBit = 0;
    for (char character : message.toCharArray()) {
      for (int bitInCharacter = 0; bitInCharacter < 7; bitInCharacter++) {
        if ((character & 1 << bitInCharacter) > 0)
          bits.set(currentBit);
        currentBit++;
      }
    }
    return bits.toByteArray();
  }

  public String decompress(byte[] compressedMessage) {
    BitSet bits = BitSet.valueOf(compressedMessage);
    int numBits = 8 * compressedMessage.length - compressedMessage.length % 7;
    StringBuilder decompressedMessage = new StringBuilder(numBits / 7);
    for (int currentBit = 0; currentBit < numBits; currentBit += 7) {
      char character = (char) bits.get(currentBit, currentBit + 7).toByteArray()[0];
      decompressedMessage.append(character);
    }
    return decompressedMessage.toString();
  }

  public static void main(String[] args) {
    String[] messages = {
      "Hello world!",
      "This is my message.\n\tAnd this is indented!",
      " !\"#$%&'()*+,-./0123456789:;<=>?\n"
        + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\n"
        + "`abcdefghijklmnopqrstuvwxyz{|}~",
      "1234567890123456789012345678901234567890"
        + "1234567890123456789012345678901234567890"
        + "1234567890123456789012345678901234567890"
        + "1234567890123456789012345678901234567890"
    };

    ASCIIConverter asciiConverter = new ASCIIConverter();
    for (String message : messages) {
      System.out.println(message);
      System.out.println("--------------------------------");
      byte[] compressedMessage = asciiConverter.compress(message);
      System.out.println("Number of ASCII characters = " + message.length());
      System.out.println("Number of compressed bytes = " + compressedMessage.length);
      System.out.println("--------------------------------");
      System.out.println(asciiConverter.decompress(compressedMessage));
      System.out.println("\n");
    }
  }
}

Журнал консоли выглядит так:

Hello world!
--------------------------------
Number of ASCII characters = 12
Number of compressed bytes = 11
--------------------------------
Hello world!


This is my message.
    And this is indented!
--------------------------------
Number of ASCII characters = 42
Number of compressed bytes = 37
--------------------------------
This is my message.
    And this is indented!


 !"#$%&'()*+,-./0123456789:;<=>?
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
`abcdefghijklmnopqrstuvwxyz{|}~
--------------------------------
Number of ASCII characters = 97
Number of compressed bytes = 85
--------------------------------
 !"#$%&'()*+,-./0123456789:;<=>?
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
`abcdefghijklmnopqrstuvwxyz{|}~


1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
--------------------------------
Number of ASCII characters = 160
Number of compressed bytes = 140
--------------------------------
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
0 голосов
/ 04 июля 2019

Неа.В «современных» средах (начиная с 3 или 4 десятилетий назад) кодировка символов ASCII для набора символов ASCII использует 8-битовые кодовые единицы, которые затем сериализуются в один байт каждый.Это потому, что мы хотим перемещать и хранить данные в «октетах» (8-битных байтах).Эта кодировка символов всегда имеет старший бит равным 0.

Можно сказать, что давно использовалась 7-битная кодировка символов для набора символов ASCII.Даже тогда данные могли быть перемещены или сохранены как октеты.Старший бит будет использоваться для некоторой специфической для приложения цели, такой как четностьНекоторые системы обнуляют его в попытке повысить совместимость, но в итоге препятствуют взаимодействию из-за отсутствия «8-битной безопасности».С сильными интернет-стандартами, такие системы почти все в прошлом.

0 голосов
/ 04 июля 2019

В зависимости от типа кодировки длина байта будет другой.Проверьте приведенный ниже пример.

String text = "0123456789";
byte[] b1 = text.getBytes(StandardCharsets.US_ASCII);
System.out.println(b1.length);
// prints "10"

byte[] utf8 = text.getBytes(StandardCharsets.UTF_8);
System.out.println(utf8.length); 
// prints "10"

byte[] utf16= text.getBytes(StandardCharsets.UTF_16);
System.out.println(utf16.length); 
// prints "22"

byte[] utf32 = text.getBytes(StandardCharsets.ISO_8859_1);
System.out.println(utf32.length); 
// prints "10" 
...