Adrian ([info]theycallmesir) wrote in [info]java_dev,
@ 2007-03-01 20:50:00
Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Base64 conversion
Need some help with some conversions.

I have a string of decimal values
85 49 86 18 12 48 195 12 48 195 12 49 194 14 56 195 14 113

which I need to convert to 6 bit ASCII values.

Taking the first 2 values as an example, if I were to do this by hand this is what it would look like.

85 is converted into a hex value of 55
55 is converted into a binary value of 01010101

49 is converted to a hex value of 31
31 is converted into a binary value of 00110001

Put the 2 binary values together to get 0101010100110001
Taking the first 6 digits of the binary, 010101 converts to a hex value of 15
15 in 6 bit Ascii is a U.
Take the next set of 6 digets of the binary, 010011 converts to a hex value of 13
13 in 6 bit Ascii is an S

Ok, so after that painful explaination.
Are there any Java utils that can do this for me?

thanks



(Post a new comment)


[info]malpingu
2007-03-02 02:36 am UTC (link)
I'm sure it took much longer for you to write that post than for me to JustFrigginGoogleIt!

(Reply to this) (Thread)


[info]theycallmesir
2007-03-02 02:43 am UTC (link)
Maybe I was looking for some real responses instead of just smart-asses.

The code I've found so far doesn't do what I want.

thanks for playing.

(Reply to this) (Parent)(Thread)


[info]asmor
2007-03-02 03:03 am UTC (link)
What you want seems rather specialized and I'd say you're prolly gonna have to make it yourself.

On the bright side, it seems like an excellent exerise in recursive algorithms.

(Reply to this) (Parent)(Thread)


[info]theycallmesir
2007-03-02 03:37 am UTC (link)
i'm starting to figure that out.
Unfortunately my hex and binary math sucks.

guess there's only one way to improve.

thanks.

(Reply to this) (Parent)


[info]malpingu
2007-03-02 05:06 am UTC (link)
Pity. I didn't expect you'd be able to use one of the common Base64 encoder without some additional work. However, as you've seen from other responses it is fairly trivial to manipulate the data into a form which can be readily used with such an encoder to achieve the result you seek.

BTW, what is the real-world application?

In so far as you judge me a smart-ass, I think you may just be lazy -- perhaps a student looking for someone else to do a simple programming assignment?

(Reply to this) (Parent)(Thread)


[info]theycallmesir
2007-03-02 06:03 am UTC (link)
the real-world, i.e. not homework, application is i'm submitting snmp get requests to a device.
the response comes back in the encoded format.

typically when someone says go google it, they have nothing to contribute to the converstation but feel the need to respond with vague non-helpful comments.
Personally I find it very annoying and attribute it to smart-asses. If someone doesn't have anything to contribute, then don't say anything at all.

This was a problem I hadn't dealt with, and admitedly in an area I'm weak in (bit manipulation) so thought it would be interesting to get other, more experienced, coders opinions on.

Take it for what you will.

(Reply to this) (Parent)(Thread)


[info]malpingu
2007-03-02 06:46 am UTC (link)
Very well. I may have misjudged your post, although to avoid such misinterpretations it might be useful to include information about what you have tried and where the difficulties lay, rather than just outline the problem to be solved. I find people more willing to help others who have attempted to help themselves and it wasn't immediately apparent that you had done so.

Also, I've been a bit cranky today. ;-) Sorry.

(Reply to this) (Parent)


[info]jojobear99
2007-03-02 03:02 am UTC (link)
There's nothing built in that's going to do exactly what you want completely automatically.

Take a look at Base64Coder.java from:
http://www.source-code.biz/snippets/java/2.htm

it looks like the encode method is pretty close to what you want. Only...your data is coming in as a string of decimal values, so you really just need to convert the string of decimal values into a byte array of binary values, and then use that as an input into that method.

So to do that, you'll probably need a StringTokenizer to break apart the string into into individual numbers (so then you have a string of "85" and then another string of "49" and so on until "194" and then so on...which is easy to convert to a byte value and add to your byte array. and then you can use the standard byte tokenizing and assignment functions. Java doesn't do unsigned types though, so you may have to play by experimentation to see whether you need a function to convert between an unsigned and signed value or not, but worry about that if you aren't getting the right output in the end...there's methods you can download online for that.

(Reply to this) (Thread)


[info]theycallmesir
2007-03-02 03:42 am UTC (link)
I started playing with that earlier today but had issues with getting the proper byte array. For example, when I did a getBytes on "85 49" I would get an array of '8' '5' '4' '9' which obviosly didn't work so well.
I was surprised to see if I had a byte of 85, it seemed to automatically translate to a 'U'. So like you say, it should just be a matter of getting the byte array correct.

Thanks for the input.

(Reply to this) (Parent)(Thread)


[info]thoth
2007-03-02 04:03 am UTC (link)
StringTokenizer is a little bloated, but if you don't need high-performance:

str = "44 55 66 77";
StringTokenizer st = new StringTokenizer(str, " ");
byte[] ba = new byte[st.countTokens()];
for (int x = 0; x < ba.length && st.hasMoreTokens(); x++) {
    ba[x] = (byte)(Integer.parseInt(st.nextToken()));
}

(Reply to this) (Parent)


[info]jojobear99
2007-03-02 05:30 am UTC (link)
yeah, if you just do getBytes on the whole string, its going to give you the byte value for each character in the string and really what you want is the byte value of each *number* in the string... so you need to break apart the string into numbers. That's where StringTokenizer comes in...breaks apart the numbers...once you have a string of a single number you can call the Byte.parseByte(stringvalue) method on each number to convert it to a byte...and if you do that in a loop for the number of tokens in the tokenizer...that's exactly how many array elements you're going to need.

here's some pseudo code:
create StringTokenizer
call method to count tokens
create byte array of same number of items
for each token (i++)
___ convert string to byte
___ insert byte value into array element i
take whole array and do the base64encode stuff

(Reply to this) (Parent)


[info]magicpete
2007-03-02 07:51 pm UTC (link)
Hiya,

Looking at this 15 hex > U and 13 hex > S would suggest a Radix 40 encoding rather than 6 bit ASCII.

Neither of these encodings are base64 as specified in http://www.faqs.org/rfcs/rfc1521.html (Section 5.2) so I'm not sure why people are suggesting you look at that... Could be that I'm confused but hey...

I wrote up a quick app to convert your string input into 6 bit ascii / radix 40 as I understand it - just replace the :

public class Ascii6Bit {

    private static char[] sixBitLookup 
        = {' ', '!', '\"', '#', '$', '%', '\'', '(', ')',
        '*', '+', ',', '-', '.', '/', '0', '1', '2', '3',
        '4', '5', '6', '7', '8', '9', ':', ';', '<', '=',
        '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
        'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
        'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[',
        '\\', ']', '^', '_'};

    private static String[] radix40Lookup
        = {null, "A", "B", "C", "D", "E", "F", "G", "H", "I", 
        "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", 
        "T", "U", "V", "W", "X", "Y", "Z", "$", " ", null,
        "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
        "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", 
        "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", 
        "?", "?", "?", "?"};
    
    
    public static void main(String[] args) {
        String input = "85 49 86 18 12 48 195 12 48 195 12 49 194 14 56 195 14 113";

        // Split the input into string representations of decimals.
        String[] asDecimals = input.split(" ");
        
        StringBuffer charBuffer = new StringBuffer();

        // A long to hold each 3 byte sequence (could actually use an int here as we're only using 
        // 3 bytes of space). Acts as a buffer. Any data already processed will be shifted off the left end.
        long charHolder = 0l;

        for (int i = 1; i <= asDecimals.length; i++) {
            // This takes the next unsigned byte and adds it to the long
            char c = (char) Integer.valueOf(asDecimals[i - 1]).intValue();

            // Shift the current value one byte to the left.
            charHolder = (charHolder << 8) + c;
            
            // process next 3 bytes
            if(i % 3 == 0) {
                
                // read the 4 6 bit values from the long.
                for (int j = 3; j >= 0; j--) {
                    long sixBitChar = (charHolder >> (j * 6)); // Shift relevant bits to end
                    // mask with 00111111 to get byte value and lookup the 6 bit representation.
                    // use this for ascii 6 bit lookup
                    charBuffer.append(sixBitLookup[(char)(sixBitChar & 0x3f)]);
                    // use this for radix 40 lookup
                    //charBuffer.append(radix40Lookup[(char)(sixBitChar & 0x3f)]);
                }
            }
        }

        System.out.println(charBuffer);
    }
}


I know I've hardcoded your string in there and not put in any error handling around the fact that the string must contain a multiple of 3 integer values, but hey - it's just demonstrating the point. What do you think?

Cheers.

(Reply to this)


[info]magicpete
2007-03-02 07:59 pm UTC (link)
oh yeah, I forgot to say that this is assuming that the encoding used ISN'T base64 in the first place - I'm not familiar with SNMP, so I have no idea!

The conversion tables I used were at: http://www.byte.com/art/9612/sec4/art4.htm

(Reply to this)


[info]magicpete
2007-03-02 08:09 pm UTC (link)
Oh, and if it was base 64 I guess you could simply plug this array in:

    private static char[] base64Lookup 
        = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
        'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c',
        'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
        'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6',
        '7', '8', '9', ' ', '/'};



but you're probably better off using one of the tried and tested implementations I guess.

(Reply to this)


Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…