Java How to read unsigned short using inputstream? - java

The C++ client send a byte array to the Java Server.The first two bytes indicate the length of the residual byte array.The client uses unsigned short,but there's no unsigned short in java.How can I read the first two bytes in my server?
And another problem is,in C++ the first byte indicates the lower 8 bits and the second byte indicates the upper 8 bits.For example,the two bytes is 35 02,it convert to decimal should to be 565,not 13570.
My java code like this:
DataInputStream dis = new DataInputStream(is);
int b1 = dis.readUnsignedByte();
int b2 = dis.readUnsignedByte();
int length = (b2 << 8) | b1;
It seems to work.But I can't make sure it is exact in any condition.I hope for your suggestions.thx~

Err, DataInputStream.readUnsignedShort()!
I can't make sure it is exact in any condition
You can't test 65536 values? It's not difficult.

To convert an unsigned short to a signed int you can do
int value = dis.readShort() & 0xFFFF;
Your other problem has to do with the byte order. I suggest taking a look at the ByteBuffer which you can specify the byte order on using the order method.

Related

Incoming Data of bytes

I am dealing with a socket connection in which I send and then receive bytes. I have the socket code written and I can both send and receive bytes but there is a catch...
I am sending data within a language called Delphi and then receiving them in the android code. But I come into a bit of a problem.
In delphi a byte has a maximum value of 255 whereas in Android the maximum byte is 127. How would you get around this? Is there a way to use an unsigned byte? Should I use shorts instead of bytes?
Any help is appreciated.
To read a single byte you can cast it to a larger Java/Android primitive type to interpret it as an unsigned value by performing a bitwise & (AND) with an 8 bit mask. To write a value to the socket as an unsigned byte value use a larger primitive type to set the value, then cast this value to a byte to write to the socket. For example:
short shortVal = 255;
byte byteVal = (byte) shortVal;
System.out.println("signed value = " + byteVal);
shortVal = (short) (byteVal & 0xFF);
System.out.println("unsigned value = " + shortVal);
Java/Android interprets the byte as a signed value (in this case, -1), but the 8 bits in the byte (11111111) are still the same as the least significant 8 bits in the short 255 (0000000011111111).
The same technique can be used with larger types (use int with 16 bit mask to interpret short as unsigned, long with 32 bit mask to interpret int as unsigned), but with multibyte values be careful to take into account the endianness of the network protocol and convert byte order if needed.

How to send value bigger than 127 in byte Java

I am working on an Smart Card where there is a method in javax.smartcardio.CommandAPDU.
CommandAPDU(int cla, int ins, int p1, int p2, byte[] data, int ne)
I need to send data as byte[] (5th argument). Now my problem is that, as Java primitive data types are signed the max value of a byte can not exceed 127. I need to send a value bigger than 127. To be precise, the hex value 94 which is equal to 148.
As some solution suggests that we can cast it to integer.
byte b = -108;
int i = b & 0xff;
I can't do that as the CommandAPDU(); constructor doesn't take an []. So how to do it?
Depending on how it is interpreted by the smart card, you could just send the correct negative value. If the smart card interprets value as unsigned, you could for example send -1 for 255.
You're calculating the APDU with unsigned bytes, while Java uses signed bytes.
It's just a matter of how the data is interpreted, sending -108 to the smart card will be interpreted in exactly the same way as sending 148 from a platform using unsigned bytes. The bit combination is exactly the same.
Java can even do the conversion itself so that you can write the code using unsigned numbers;
byte data = (byte)0x94; // stores -108 in "data", which will be interpreted
// as 148 on an unsigned platform
For long blocks of data, it is probably best to use a hexadecimal encoder/decoder. But be sure that you handle the data as bytes internally (directly decode and don't look back to the hex String). The Apache codec library contains a good encoder/decoder, or you can use Bouncy Castle or Guava or use one of the many examples on SO.

C++/Java - int(0 - 1023) to byte Array (two bytes only)

How do I get the following int to a byte array. I have been reading other SO questions and everything is confusing, could someone explian what is happening in the code.
int val = 1023; // the int will vary from 0 to 1023 (it's the analogRead value from an Arduino board)
the purpose of me wanting this as a byte array is so that i can use it for Arduino's server.write().
This is what I've come up with so far:
int val = analogRead(A0);
Serial.println(val);
byte value[2];
value[1] = val & 0x000000ff;
value[0] = (val & 0x0000ff00) >> 8;
server.write(value[0]);
server.write(value[1]);
I am trying to communicate TCP with an Android application I have written, here is the recieving end:
mmInStream = mmSocket.getInputStream();
final byte[] buffer = new byte[16384]; // two bytes
int bytes;
bytes = mmInStream.read(buffer);
Log.d(null,buffer[0]+buffer[1]);
is this correct?
The Arduino console is spitting out the values, example:
870
870
870
872
However my Android application is spitting out the following, example:
3102
3105
1033
1035
I must be doing something wrong here!
ANSWER: Arduino sends unsigned bytes, java recieves only signed bytes. I fixed it with a little code on the java end.
Whenever you're going to be dealing with some binary communications protocol, be it a TCP connection, Serial Port, USB, etc. you need to save yourself some future headaches and define your protocol.
Specifically, this means field widths, and byte order. When sending binary data over a network protocol, we almost always send it in "network order", which is "big-endian", meaning the most-significant byte first.
Example: I want to send a four-byte int a = 0x12345678 over the network. If you do it correctly, the bytes go out in the order 12 34 56 78.
However, I believe your ATMEGA chip is little-endian, which means that bytes are stored (in memory) with the least-significant byte first. So if you were to just cast that int to a unsigned char* and send 4 bytes, they would go out in the order 78 56 34 12.
So in order to send that value out, you should first decide how many bytes it's going to be. Since you've limited it to the range 0 - 1023, you've observed that it will fit into just two bytes. Good. So your protocol is:
Offset 0: value Size: 2
Now, you need to send it in network order. Your example code:
byte value [2];
value[1] = val & 0x000000ff;
value[0] = (val & 0x0000ff00) >> 8;
is putting the most significant byte at position 0, and the least significant byte at position 1. So a value of 0x1234 will go out in the order 12 34. Perfect.
Your code is correct (on the Arduino side).
Now, on the receiving side, you need to make sure that you're receiving data in network order also. I haven't done any Java network programming, so you'll need to check with the documentation to see how it handles network binary streams. In particular, when you go to read that "16-bit unsigned integer" from the network, the byte order needs to be respected.
Perhaps this will help you on the Java side:
network byte order to host byte order in java
This will encode an int as a byte array.
// Encoding
byte value[2] = { highByte(val), lowByte(val) };
This will convert a byte array back to an integer
// Decoding
int val = value[0] << 8 + value[1];

How to read unsigned values from files

I am trying to read binary data (Doom WAD files), which contain a lot of unsigned short and unsigned byte values.
At the moment I read the file into a byte[], wrap a ByteBuffer with little-endian order around it and access the values by bbuf.getShort() etc. respectively.
Converting those e. g. to 2D-coordinates is not a problem, because in the end it won't matter if they range eg. from -128 to 128 or from 0 to 256, but more often the short values are used as array indices and short/byte values as flags/, so I need a fast way to treat them as signed types.
I know, Java doesn't have unsigned types "for sake of simplicity...".
Can you make any suggestions?
In order to save unsigned ints you need a long. Then you need to truncate last 32 bits. You can use following trick to do it.
final long UNSIGNED_INT_BITS = 0xffffffffL;
int a = -3;
long b = UNSIGNED_INT_BITS & a;
System.out.println(a);
System.out.println(b);
System.out.println(Long.toHexString(UNSIGNED_INT_BITS));
Output:
-3
4294967293
ffffffff
If all else fails, you could always store them internally as ints and make sure you do proper conversion when reading/writing.
(Read as byte/short, cast to int, add 2^bits if negative. Just truncate to 8/16 bits when writing.)
Hardly the most elegant solution, I admit.
If you need to interprete 0xFF byte as 256 do the following
int n = b & 0xFF;

Converting raw-byte values into Java types

I have a problem with converting raw-bytes values into java types. I am receiving bytes by a datagram socket as a bytes array. I know exactly which bytes means what, but I don't know how to convert them appropriately (I mean I know offsets, but don't know if what I think I received is correct ;)).
For example, I want to convert 16 bit unsigned short into java int type. I found some examples in the web, the one is:
public int getUShort(byte[] bytes, int offset) {
int b0 = bytes[offset] & oxFF;
int b1 = bytes[offset + 1] & oxFF;
return (b1 << 8) + (b0 << 0);
Another one is the same but the last line is:
return (b0 << 8) + b1;
Of course it gives different results. Which one is correct? Can you please give me also a valid example how to do the same but for an unsigned long?
Thank you in advance!
I had to do some work similar to this a while back and I found that the best way to do this sort of work is to use ByteBuffer and its conversions to DoubleBuffer, LongBuffer, etc. You can convert an array of bytes into a ByteBuffer by calling
ByteBuffer myBuffer = ByteBuffer.wrap(myRawArray);
From there, you can get a view of the bytes as a list of ints by calling
IntBuffer myIntBuffer = myBuffer.asIntBuffer();
and you can then convert the bytes by calling
int nextInt = myIntBuffer.get();
These classes also have lots of support for bulk get operations, so if you know for a fact that you're receiving a whole bunch of data of the same type over the network you can do the conversions very quickly.
An alternative approach would be, if at all possible, to use some sort of Java-based serialization to send the data over the network. This allows you to do the conversions much more easily using the stream writer classes. Of course, this might not be available, especially if you're communicating with a non-Java server, but it might be worth exploring.
You can use DataInputStream or ByteBuffer to read the various types. You can use signed types as unsigned values for most operations just the same. I have written a simple class to illustrate how you can use the signed types as if they were unsigned Unsigned
ByteBuffer b = ByteBuffer.wrap(bytes);
short s = b.getShort();
long l = b.getLong();
Really late on this one.
Both are correct based on the endianess of the data. See here: http://en.wikipedia.org/wiki/Endianness
return (b1 << 8) + b0;//little endian
return (b0 << 8) + b1;//big endian

Categories