Как конвертировать 24 байта BCD в ASCII в Java? - PullRequest
0 голосов
/ 19 мая 2010

Я хочу преобразовать 24-байтовый BCD в ASCII. Я пытаюсь написать некоторый код для этого преобразования, но я не уверен, как сделать для него математические вычисления. Предложения?

Это мои входные данные, cd00320000a4002a00001042 Тег (24-байтовый BCD)

Ответы [ 6 ]

5 голосов
/ 19 мая 2010

Это будет работать:

StringBuilder sb = new StringBuilder(bcdDigits.length * 2);
for (byte b : bcdDigits) {
  sb.append(String.format("%02x", b));
}
System.out.println(sb.toString());

Упакованное преобразование BCD-> String, по сути, аналогично преобразованию в шестнадцатеричную строку, только без символов a-f.

1 голос
/ 20 мая 2010

Этот вопрос является единственным случаем '24-байтовой BCD', которую индексирует Google; и ваш пример не имеет длину 24 байта и не является BCD. Какой формы ASCII в приведенном вами примере вы видите?

Мне интересно, является ли ваш 12-байтовый пример чем-то вроде тега ASN.1, означающего «следующие данные являются 24-байтовой BCD», а не частью 24-байтовой BCD.

0 голосов
/ 19 мая 2010

Есть два подхода, которые я могу использовать. Сначала вы могли бы использовать простой включите две составляющие байта, чтобы извлечь каждую десятичную цифру:

public static String bcdToString(byte[] bcd){
  StringBuilder s = new StringBuilder(bcd.length*2);
  char c = ' ';
  for(byte b : bcd){
    switch((b>>4)&0xF){
      case 0: c = '0';break;
      case 1: c = '1';break;
      case 2: c = '2';break;
      case 3: c = '3';break;
      case 4: c = '4';break;
      case 5: c = '5';break;
      case 6: c = '6';break;
      case 7: c = '7';break;
      case 8: c = '8';break;
      case 9: c = '9';break;
      default: throw new IllegalArgumentException("Bad Decimal: "+((b>>4)&0xF));
    }
    s.append(c);
    switch(b&0xF){
      case 0: c = '0';break;
      case 1: c = '1';break;
      case 2: c = '2';break;
      case 3: c = '3';break;
      case 4: c = '4';break;
      case 5: c = '5';break;
      case 6: c = '6';break;
      case 7: c = '7';break;
      case 8: c = '8';break;
      case 9: c = '9';break;
      default: throw new IllegalArgumentException("Bad Decimal: "+(b&0xF));
    }
    s.append(c);
  }
  /* If you want to remove a leading zero:
     if(s.charAt(0) == '0') return s.substring(1);
  */
  return s.toString();
}

В качестве альтернативы вы можете использовать карту для поиска значений:

private static HashMap<Byte, String> digits = new HashMap<Byte, String>();
static{
  for(byte b1=0;b1<10;b1++){
    for(byte b2=0;b2<10;b2++){
      digits.put((byte)((b1<<4)|b2), Byte.toString(b1)+Byte.toString(b2));
    }
  }
}

public static String bcdToString2(byte[] bcd){
  StringBuilder s = new StringBuilder(bcd.length*2);
  String tmp = null;
  for(byte b : bcd){
    tmp = digits.get(b);
    if(tmp == null) throw new IllegalArgumentException("Bad bcd: "+Integer.toString(b, 16));
    s.append(tmp);
  }
  /* If you want to remove a leading zero:
     if(s.charAt(0) == '0') return s.substring(1);
  */
  return s.toString();
}

Я не уверен, что у одного будет какой-либо прирост производительности по сравнению с другим, поскольку я не проверял это.

0 голосов
/ 19 мая 2010

Преобразуйте его в int и отформатируйте в текст. Например,

public static int bcdToInt(final int bcd) {
    int result = 0;
    for (int i = 0; i < 8; i++) {
        result += (0xF & bcd >> 4 * i) * (int)Math.pow(10,i);
    }
    return result;
}

int n = bcdToInt(bcd);
String text = String.format("%010d", n);
0 голосов
/ 19 мая 2010

Что вы подразумеваете под преобразованием BCD в ASCII? По сути, это уже ASCII, у вас есть что-то вроде 0x73, которое вы хотите преобразовать в «73», так что

left = (char) (48+ (A >> 4)); правый = (символ) (48+ (A & 15); выходная строка + = символ.строка (слева) + символ.строка (справа);

0 голосов
/ 19 мая 2010

Если вы имеете в виду BCD как двоично-десятичное десятичное число, то вам просто нужно преобразовать каждую половину байта (иногда называемого nybble :)) в одну десятичную цифру. Если у вас есть пример ваших входных данных, тогда я могу дать вам более конкретный ответ, но что-то вроде этого:

String s = "";
for (byte b : input) {
  int hi = b >>> 4;
  int lo = b & 0xF;
  if (hi > 9 || lo > 9)
    throw new IllegalArgumentException();
  s = s + hi.toString() + lo.toString();
}

Очевидно, что это можно улучшить (например, с помощью StringBuilder), но, надеюсь, вы поймете эту идею (подробности о побитовых операторах, используемых для вычисления hi и lo, см. http://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html).

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