Monday, 16 August 2010

Java unsigned int to signed byte and back again

In the last month or so I've been spending a lot of time playing with protocols in Java. Having previously done this kind of work in either .NET or C++ I had become accustomed to having unsigned data types available to me. So coming to Java I was a little shocked that they were missing. This seems somewhat accepted in the Java community so I am, of course, going with the flow.

Despite Java having some very useful classes like the java.io ByteArrayInputStream and ByteArrayOutputStream I found very little information out there on what exactly happens when you want to read or write unsigned byte values. So I wrote a little bit of test code to prove that my understanding was correct:


int in, out;
byte b;

in = 0;
b = (byte)in;
out = b & 0xff;
System.out.println("in=" + in + ", b=" + b + ", out=" + out);


in = 127;
b = (byte)in;
out = b & 0xff;
System.out.println("in=" + in + ", b=" + b + ", out=" + out);


in = 128;
b = (byte)in;
out = b & 0xff;
System.out.println("in=" + in + ", b=" + b + ", out=" + out);


in = 255;
b = (byte)in;
out = b & 0xff;
System.out.println("in=" + in + ", b=" + b + ", out=" + out);

Which produces the following output to the Console:


in=0, b=0, out=0
in=127, b=127, out=127
in=128, b=-128, out=128
in=255, b=-1, out=255

Hopefully this might be of use to somebody. It certainly made me feel more at ease 'flinging them bytes about'!

Java String valueOf and StringBuilder append - int and char differences

I'm in the middle of writing some code which uses the InputStream read function. InputStream.read() returns a value of -1 when you get to the end of the stream but until that point it returns a byte (0 to 255).

I am pushing these bytes to a StringBuilder and wanted them to be interpreted as their ASCII character codes. What's not obvious from the documentation is that char is treated very differently from other numbers pushed to a StringBuilder with the append function.

The documentation for StringBuilder append(char) states: Appends the string representation of the specified char value. The char value is converted to a string according to the rule defined by valueOf(char).

The documentation for StringBuilder append(int) states: Appends the string representation of the specified int value. The int value is converted to a string according to the rule defined by valueOf(int).

Identical definitions!

The documentation for String valueOf(char) states: Converts the specified character to its string representation. Returns the character converted to a string.

The documentation for String valueOf(int) states: Converts the specified integer to its string representation. Returns the integer converted to a string.

Again, identical definitions. But...

This test code:
int a = 65;
int b = 66;
StringBuilder sb = new java.lang.StringBuilder();
sb.append("int a = [");
sb.append(a);
sb.append("], char a = [");
sb.append((char)a);
sb.append("], int b = [");
sb.append(b);
sb.append("], char b = [");
sb.append((char)b);
sb.append("]");
System.out.println(sb.toString());

Produces this console output:
int a = [65], char a = [A], int b = [66], char b = [B]

As tested against the Java SE 6 SDK.

Which confirms that StringBuilder append and String valueOf behave differently for int and char types. For my particular requirements here this is the behaviour I wanted - and logical enough to cast an int to char to get this behaviour. But to someone who might be coming from a different programming environment (say, for example, one with unsigned data types!) then this might not be so obvious - hence why I've posted this article!