Byte buffer in Java? - java

Since I found out that it's impossible to have unsigned bytes in java, and that essentially they take up the same memory as an int, is there really any difference when you send them over a packet?
If I send a Java byte via tcp or udp via(Games.RealTimeMultiplayer.sendReliableMessage) would that be more beneficial to me than just sending an integer to represent an unsigned byte?

Since I found out that it's impossible to have unsigned bytes in java
This is incorrect. There are lots of ways. You can even use byte to represent an unsigned byte. You just need to perform a mapping in places that require it; e.g.
byte b = ...
int unsigned = (b >= 0) ? b : (b + 256);
... and that essentially they take up the same memory as an int.
That is also incorrect. It is true for a byte variable or field. However, the bytes in a byte array occupy 1/4 of the space of integers in an int array.
... is there really any difference when you send them over a packet?
Well yes. A byte sent over the network (in the natural fashion) takes 1/4 of the number of bits as an int sent over the network. If you are sending an "8 bit quantity" as 32 bits, then you are wasting network bandwidth.

Related

Get least significant bytes from an integer

I need to sum all data bytes in ByteArrayOutputStream, adding +1 to the result and taking the 2 least significant bytes.
int checksum = 1;
for(byte b : byteOutputStream.toByteArray()) {
checksum += b;
}
Any input on taking the 2 least significant bytes would be helpful. Java 8 is used in the environment.
If you really mean least significant bytes then:
checksum & 0xFFFF
If you meant that you want to take least significant bits from checksum, then:
checksum & 0x3
Add
checksum &= 0x0000ffff;
That will zero out everything to the left of the 2 least significant bytes.
Your question is a bit underspecified. You didn’t say neither, what you want to do with these two bytes nor how you want to store them (which depends on what you want to do).
To get to individual bytes, you can use
byte lowest = (byte)checksum, semiLowest=(byte)(checksum>>8);
In case you want to store them in a single integer variable, you have to decide, how these bytes are to be interpreted numerically, i.e signed or unsigned.
If you want a signed interpretation, the operation is as simple as
short lowest2bytes = (short)checksum;
If you want an unsigned interpretation, there’s the obstacle that Java has no dedicated type for that. There is a 2 byte sized unsigned type (char), but using it for numerical values can cause confusion when other code tries to interpret it as character value (i.e. when printing). So in that case, the best solution is to use an int variable again and only initialize it with the unsigned char value:
int lowest2bytes = (char)checksum;
Note that this is semantically equivalent to
int lowest2bytes = checksum&0xffff;
seen in other solutions.

Representing signed byte in an unsigned byte variable

I apologies if the title of this question is not clear, but i cannot figure out the best way to describe my predicament in so few words.
I am writing a communication framework between java and C# using sockets and byte by byte transfer of information.
I have ran into an issue which has been confusing me for a good few hours now. As you hopefully know. java's byte base type is signed, meaning it can store -128 to +127 if you were to represent it in integer form. C# however, uses unsigned bytes, meaning that it store 0-255 in integer form.
This is where i am encountering the issue. If need to send some bytes of information from my c# client to my java server, i use the following code:
C#:
MemoryStream stream;
public void write(byte[] b, int off, int len) {
stream.Write(b, off, len);
}
Java:
DataInputStream in;
public int read(byte[] b, int off, int len) throws IOException{
in.read(b, off, len));
}
As you can see these are very very similar pieces of code that when used within their own languages will produce predictable results. However, due to the differences in the signing these will produce unusable data.
I.e if i send 255 from my c# client to java server, I will receive a value of -1 on the java server. This is because both of those values are represented of these 8 bits: 11111111
Preferably in order to solve this problem I would need to use the following code, using sbyte, c#'s signed byte.
C#:
MemoryStream stream;
public void write(sbyte[] b, int off, int len) {
//Code to change sbyte into a byte but keeping it in the form in which java will understand
stream.Write(b, off, len);
}
I basically need to store java's representation of a signed byte inside an unsigned C# byte in order to send that byte across to the server. I will also need to do this in reverse to get an sbyte out of a byte received from my java server.
I have tried numerous ways in which to do this with no success. If anyone has any idea as to how i can go about this i would be GREATLY appreciative.
You basically don't need to do anything except stop thinking about bytes as numbers. Think of them as 8 bits, and Java and C# are identical. It's rare that you really want to consider a byte as a magnitude - it's usually just binary data like an image, or perhaps encoded text.
If you want to send the byte 10100011 across from Java to C# or vice versa, just do it in the most natural way. The bits will be correct, even if the byte values will be different when you treat them as numbers.
It's not entirely clear what data you're actually trying to propagate, but in 99.9% of cases you can just treat the byte[] as opaque binary data, and transmit it without worrying.
If you do need to treat the bytes as magnitudes, you need to work out which range you want. It's easier to handle the Java range, as C# can support it with sbyte[]... but if you want the range 0-255, you just need to convert the byte to an int on the Java side and mask it with the bottom 8 bits:
byte b = ...;
int unsigned = b & 0xff;
If you really need to treat byte[] as sbyte[] or vice versa on C#, you can use a little secret: even though C# doesn't allow you to convert between the two, the CLR does. All you need to do is go via a conversion of the reference to object to fool the C# compiler into thinking it might be valid - otherwise it thinks it knows best. So this executes with no exceptions:
byte[] x = new byte[] { 255 };
sbyte[] y = (sbyte[]) (object) x;
Console.WriteLine(y[0]); // -1
You can convert in the other direction in exactly the same way.

Create unsigned byte for serial port use

I need to write a java program that will send byte through serial port. I am using the rxtx library. The problem is that in Java everything is signed, and in one byte I need to send 0xfc, but in Java this is signed, and it defined as -4. So how can I make an unsigned byte in java, so that in one byte I can send from 0 to 255?
It's fine - you can just cast where required. If you have an API which lets you send bytes, and you send a byte of -4 in Java, the bit pattern will be the same as for an unsigned byte 0xfc.
If you have a value as an int or short in the range 0-255, just cast that to byte, and again it will represent the right bit pattern, even though the value will become negative if the original value was above 127.
This will work
public static int unsignedToBytes(byte b) {
return b & 0xFF;
}
For a byte b , b & 0xFF will return the unsigned integer value .. will that be okay for you??

CRC calculation in Java

I'm reading a file from serialport using x-modem protocol and 133 bytes packet. I'm reading
in that
1 byte is SOH
2 byte packet number
3 byte nagative of packet number
next 128 bytes data
2 bytes CRC sent from other side.
I have to calculate CRC of 128 bytes data and 2 bytes crc sent from other side that I have to make it single byte and have to comapare with my calculated crc. How can I do this in java?
Try using Jacksum.
Sun JDK 1.6 contains sun.misc.CRC16, but there is a possibility this is not the CRC16 you're looking for, since there's several different polynomials in use.
Here is my C code, which is trivial to port to Java - you are free to use it in any way you like. The references to word are for a 16 bit unsigned value - you should be able to use a char instead in Java.
It's been too long since I worked with 16 bit CRC's so I don't recall if there are variations based on seeding. I am pretty sure I used this code in a C implementation of X-Modem way back when.
The source is posted on tech.dolhub.com.

Does Java read integers in little endian or big endian?

I ask because I am sending a byte stream from a C process to Java. On the C side the 32 bit integer has the LSB is the first byte and MSB is the 4th byte.
So my question is: On the Java side when we read the byte as it was sent from the C process, what is endian on the Java side?
A follow-up question: If the endian on the Java side is not the same as the one sent, how can I convert between them?
Use the network byte order (big endian), which is the same as Java uses anyway. See man htons for the different translators in C.
I stumbled here via Google and got my answer that Java is big endian.
Reading through the responses I'd like to point out that bytes do indeed have an endian order, although mercifully, if you've only dealt with “mainstream” microprocessors you are unlikely to have ever encountered it as Intel, Motorola, and Zilog all agreed on the shift direction of their UART chips and that MSB of a byte would be 2**7 and LSB would be 2**0 in their CPUs (I used the FORTRAN power notation to emphasize how old this stuff is :) ).
I ran into this issue with some Space Shuttle bit serial downlink data 20+ years ago when we replaced a $10K interface hardware with a Mac computer. There is a NASA Tech brief published about it long ago. I simply used a 256 element look up table with the bits reversed (table[0x01]=0x80 etc.) after each byte was shifted in from the bit stream.
There are no unsigned integers in Java. All integers are signed and in big endian.
On the C side the each byte has tne LSB at the start is on the left and the MSB at the end.
It sounds like you are using LSB as Least significant bit, are you? LSB usually stands for least significant byte.
Endianness is not bit based but byte based.
To convert from unsigned byte to a Java integer:
int i = (int) b & 0xFF;
To convert from unsigned 32-bit little-endian in byte[] to Java long (from the top of my head, not tested):
long l = (long)b[0] & 0xFF;
l += ((long)b[1] & 0xFF) << 8;
l += ((long)b[2] & 0xFF) << 16;
l += ((long)b[3] & 0xFF) << 24;
There's no way this could influence anything in Java, since there's no (direct non-API) way to map some bytes directly into an int in Java.
Every API that does this or something similar defines the behaviour pretty precisely, so you should look up the documentation of that API.
I would read the bytes one by one, and combine them into a long value. That way you control the endianness, and the communication process is transparent.
Imho there is no endianness defined for java. The endianness is the one of the hardware but java is highlevel and hides the hardware so you don't have to wory about that.
The only endianess related feature is how the java lib maps int and long to byte[] (and inversely). It does it Big-Endian which is the most readable and natural:
int i=0xAABBCCDD
maps to
byte[] b={0xAA,0xBB,0xCC,0xDD}
If it fits the protocol you use, consider using a DataInputStream, where the behavior is very well defined.
Java is 'Big-endian' as noted above. That means that the MSB of an int is on the left if you examine memory (on an Intel CPU at least). The sign bit is also in the MSB for all Java integer types.
Reading a 4 byte unsigned integer from a binary file stored by a 'Little-endian' system takes a bit of adaptation in Java. DataInputStream's readInt() expects Big-endian format.
Here's an example that reads a four byte unsigned value (as displayed by HexEdit as 01 00 00 00) into an integer with a value of 1:
// Declare an array of 4 shorts to hold the four unsigned bytes
short[] tempShort = new short[4];
for (int b = 0; b < 4; b++) {
tempShort[b] = (short)dIStream.readUnsignedByte();
}
int curVal = convToInt(tempShort);
// Pass an array of four shorts which convert from LSB first
public int convToInt(short[] sb)
{
int answer = sb[0];
answer += sb[1] << 8;
answer += sb[2] << 16;
answer += sb[3] << 24;
return answer;
}
java force indeed big endian : https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.11

Categories

Resources