I want to conv开发者_Python百科ert 24 byte BCD to ASCII.Im trying to write some code for this conversion but Im not sure how to do the math for it. Suggestions?
This is my input data, cd00320000a4002a00001042 Tag (24 Byte BCD)
This would work:
StringBuilder sb = new StringBuilder(bcdDigits.length * 2);
for (byte b : bcdDigits) {
sb.append(String.format("%02x", b));
}
System.out.println(sb.toString());
Packed BCD->String conversion is essentially the same as conversion to hexadecimal string, only without a-f characters.
This question is the only occurrence of '24 byte BCD' that Google indexes; and your example is not 24 bytes long and is not BCD. What do you expect the ASCII form of the example you gave to be?
I'm wondering whether your 12-byte example is actually something like an ASN.1 tag meaning 'the following data is 24-byte BCD', rather than a piece of 24-byte BCD itself.
What do you mean by converting BCD to ASCII? It's essentially ASCII already, you have something like 0x73 which you want to convert to "73", so do
left = (char)(48+(A>>4)); right = (char)(48+(A&15); outputstring += Character.toString(left)+Character.toString(right);
Convert it to int and format it into text. For example,
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);
If you mean BCD as binary coded decimal then you just need to convert each half a byte (sometimes called a nybble :) ) into a single decimal digit. If you have an example of your input data then I can give you a more concrete answer, but something like this:
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();
}
Could obviously be improved (by using StringBuilder for instance) but hopefully you get the idea (see http://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html for details of the bitwise operators used to compute hi and lo).
There are two approaches I can think of to use. First you could use a simple switch on the two components of the byte to pull out each decimal digit:
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();
}
Alternatively you could use a map to look up the values:
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();
}
I'm not sure if one would have any performance gains over the other, as I didn't test that.
精彩评论