I have a an array of bytes I'm calculating a checksum for in Java. And I'm trying to convert it to Kotlin. But the problem is that I am getting different values when calculating the -128 & 0xff in Java than it's equivalent in Kotlin. When passing in the -128, when I make the calculation in Java, it gives me a positive 128, but when I run it in Kotlin, it gives me a -128.
public class Bytes {
public static byte[] getByteArray() {
return new byte [] {-128};
}
public static int getJavaChecksum() {
int checksum = 0;
for (Byte b : getByteArray()) {
checksum += (b & 0xff);
}
return checksum;
}
}
This is my Kotlin code. I'm calling into the above bytes class to get the "byte array" I'm working with. So both pieces are running on the same input.
fun getKotlinChecksum(array: ByteArray): Byte {
var checksum = 0
for (b in array) {
checksum += (b and 0xFF.toByte())
}
return checksum.toByte()
}
fun main(args: Array<String>) {
println(Bytes.getJavaChecksum())
print(getKotlinChecksum(Bytes.getByteArray()))
}
The Java code is from a legacy code base that uses I2C to send over these bytes to a microcontroller. Is the Java just wrong? Or is there a way that I can get the 128 in the Kotlin code?
Returning a Byte means the function cannot return 128 no matter what, so that needs to be Int. The Java checksum does a "full" sum, not just the lowest byte of the sum. Similarly the bitwise AND cannot be done on bytes, that is useless, the sign extension (the AND with 0xFF is to remove the extended sign bits) would still happen. Then it could be written as a loop, Java style, but in Kotlin it probably makes more sense to write something like this:
fun getKotlinChecksum(array: ByteArray): Int {
return array.map({ it.toInt() and 0xFF }).sum()
}
Related
The read() function reads one byte at a time and the return type of this function is int. I want to know what happens under the hood so that byte is returned as an int. I have no knowledge of bitwise operators so can anyone answer in a way that i grasp it readily.
It depends on the stream implementation. In some cases the method implementation is in native code. In others, the logic is simple; for example, in ByteArrayInputStream the read() method does this:
public class ByteArrayInputStream extends InputStream {
protected byte buf[];
protected int count;
protected int pos;
...
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
}
In other words, the bytes are converted into integers in the range 0 to 255, like the javadoc states, and -1 is returned at the logical end-of-stream.
The logic of buf[pos++] & 0xff is as follows:
buf[pos++] is converted to an int
& 0xff converts the signed integer (-128 to +127) into an "unsigned" byte (0 to 255) represented as an integer.
Under the hood, if the end of stream is reached, read() returns -1. Otherwise, it returns the byte value as an int (the value is thus between 0 and 255).
After you've verified that the result is not -1, you can get the signed byte value using
byte b = (byte) intValue;
That will just keep the 8 rightmost bits of the int, and the 8th bit from the right is used as the sign bit, thus leading to a signed value, between -128 and 127.
If the method returned a byte, there would be no way, other than throwing an exception, to signal that the end of the stream has been reached.
Below is the program to read one byte at a time using read() method of InputStream:
public class Main {
public static void main(String[] args) {
try {
InputStream input = new FileInputStream("E:\\in.txt");
int intVal;
while((intVal = input.read()) >=0)
{
byte byteVal = (byte) intVal;
System.out.println(byteVal);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Please not that the intVal here returned by input.read() is the byte value of the characters read from file in.txt.
So far I've been using the following code to convert signed to unsigned values that I need to send as a byte array over UDP to an embedded system.
public static byte serializeShort(short a)
{
return ((byte) (a & 0xFF));
}
public static short serializeInt(int a)
{
return ((short) (a & 0xFFFF));
}
public static int serializeLong(long a)
{
return ((int) (a & 0xFFFFFFFF));
}
The issue with the long, is some values can be real values. The output of this method I put into a bytebuffer via put(), putInt(), or putShort().
Any idea on how to translate the signed to unsigned for a double type?
Specifically here is my problem:
I have a UINT32 value that is being populated. I'm filling in my byte buffer with either a java signed LONG or a java signed double. I used the 'serializeLong()' above for the longs and it works fine, but the doubles do not.
ByteBuffer buffer = ByteBuffer.allocate(SIZE);
if (value instanceof Long)
{
buffer.putInt(Util.serializeLong((Long) value));
} else
{
buffer.putInt(Util.serializeLong(Double.doubleToLongBits((Double) value)));
}
Instead of using a Double, you should be using a float and to get it into the uint32 space use: buffer.putInt((Float.floatToRawIntBits(Math.abs((Float) value))));
I have integers from 0 to 255, and I need to pass them along to an OutputStream encoded as unsigned bytes. I've tried to convert using a mask like so, but if i=1, the other end of my stream (a serial device expecting uint8_t) thinks I've sent an unsigned integer = 6.
OutputStream out;
public void writeToStream(int i) throws Exception {
out.write(((byte)(i & 0xff)));
}
I'm talking to an Arduino at /dev/ttyUSB0 using Ubuntu if this makes things any more or less interesting.
Here's the Arduino code:
uint8_t nextByte() {
while(1) {
if(Serial.available() > 0) {
uint8_t b = Serial.read();
return b;
}
}
}
I also have some Python code that works great with the Arduino code, and the Arduino happily receives the correct integer if I use this code in Python:
class writerThread(threading.Thread):
def __init__(self, threadID, name):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
def run(self):
while True:
input = raw_input("[W}Give Me Input!")
if (input == "exit"):
exit("Goodbye");
print ("[W]You input %s\n" % input.strip())
fval = [ int(input.strip()) ]
ser.write("".join([chr(x) for x in fval]))
I'd also eventually like to do this in Scala, but I'm falling back to Java to avoid the complexity while I solve this issue.
I think you just want out.write(i) here. Only the eight low-order bits are written from the int argument i.
Cast, then mask: ((byte)(i)&0xff)
But, something is very strange since:
(dec)8 - (binary)1000
(dec)6 - (binary)0110
[edit]
How is your Arduino receiving 6 (binary)0110 when you send 1 (binary)0001?
[/edit]
I have one array of bytes. I want to access each of the bytes and want its equivalent binary value(of 8 bits) so as to carry out next operations on it. I've heard of BitSet but is there any other way of dealing with this?
Thank you.
If you just need the String representation of it in binary you can simply use Integer.toString() with the optional second parameter set to 2 for binary.
To perform general bit twiddling on any integral type, you have to use logical and bitshift operators.
// tests if bit is set in value
boolean isSet(byte value, int bit){
return (value&(1<<bit))!=0;
}
// returns a byte with the required bit set
byte set(byte value, int bit){
return value|(1<<bit);
}
You might find something along the lines of what you're looking in the Guava Primitives package.
Alternatively, you might want to write something like
public boolean[] convert(byte...bs) {
boolean[] result = new boolean[Byte.SIZE*bs.length];
int offset = 0;
for (byte b : bs) {
for (int i=0; i<Byte.SIZE; i++) result[i+offset] = (b >> i & 0x1) != 0x0;
offset+=Byte.SIZE;
}
return result;
}
That's not tested, but the idea is there. There are also easy modifications to the loops/assignment to return an array of something else (say, int or long).
BitSet.valueOf(byte[] bytes)
You may have to take a look at the source code how it's implemented if you are not using java 7
Java has bitwise operators. See a tutorial example.
The Java programming language also provides operators that perform bitwise and bit shift operations on integral types. The operators discussed in this section are less commonly used. Therefore, their coverage is brief; the intent is to simply make you aware that these operators exist.
The unary bitwise complement operator "~" inverts a bit pattern; it can be applied to any of the integral types, making every "0" a "1" and every "1" a "0". For example, a byte contains 8 bits; applying this operator to a value whose bit pattern is "00000000" would change its pattern to "11111111".
A byte value IS integral, you can check bit state using masking operations.
The least significant bit corresponds to the mask 1 or 0x1, the next bit correspond to 0x2, etc.
byte b = 3;
if((b & 0x1) == 0x1) {
// LSB is on
} else {
// LSB is off
}
byte ar[] ;
byte b = ar[0];//you have 8 bits value here,if I understood your Question correctly :)
Well I think I get what you mean. Now a rather substantial error with this is that it doesn't work on negative numbers. However assuming you're not using it to read file inputs, you might still be able to use it.
public static ArrayList<Boolean> toBitArr(byte[] bytearr){
ArrayList<Boolean> bitarr = new ArrayList<Boolean>();
ArrayList<Boolean> temp = new ArrayList<Boolean>();
int i = 0;
for(byte b: bytearr){
while(Math.abs(b) > 0){
temp.add((b % 2) == 1);
b = (byte) (b >> 1);
}
Collections.reverse(temp);
bitarr.addAll(temp);
temp.clear();
}
return bitarr;
}
Here is a sample, I hope it is useful for you!
DatagramSocket socket = new DatagramSocket(6160, InetAddress.getByName("0.0.0.0"));
socket.setBroadcast(true);
while (true) {
byte[] recvBuf = new byte[26];
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
socket.receive(packet);
String bitArray = toBitArray(recvBuf);
System.out.println(Integer.parseInt(bitArray.substring(0, 8), 2)); // convert first byte binary to decimal
System.out.println(Integer.parseInt(bitArray.substring(8, 16), 2)); // convert second byte binary to decimal
}
public static String toBitArray(byte[] byteArray) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < byteArray.length; i++) {
sb.append(String.format("%8s", Integer.toBinaryString(byteArray[i] & 0xFF)).replace(' ', '0'));
}
return sb.toString();
}
I'm trying to represent the port number 9876 (or 0x2694 in hex) in a two byte array:
class foo {
public static void main (String args[]) {
byte[] sendData = new byte[1];
sendData[0] = 0x26;
sendData[1] = 0x94;
}
}
But I get a warning about possible loss of precision:
foo.java:5: possible loss of precision
found : int
required: byte
sendData[1] = 0x94;
^
1 error
How can I represent the number 9876 in a two byte array without losing precision?
NOTE: I selected the code by #Björn as the correct answer, but the code by #glowcoder also works well. It's just a different approach to the same problem. Thank you all!
Have you tried casting to a byte ? e.g.
sendData[1] = (byte)0x94;
0x94 is 148 in decimal, which exceeds the range of byte in java (-128 to 127).
You can do one of the following:
1) A cast will work fine because it will preserve the binary representation (no meaningful bits are truncated for 0x00 to 0xFF):
sendData[1] = (byte)0x94;
2) The binary representation of 0x94 as a signed byte is -108 (-0x6C), so the following will have the same effect:
sendData[1] = -0x6C; //or -108 in decimal
Björn gave a good generic answer with using streams. You can also do this same thing using java.nio.ByteBuffer which results in slightly less code and you could also control endianess (byte order) of the output.
To create the byte array:
public static byte[] toByteArray(int bits) {
ByteBuffer buf = ByteBuffer.allocate(4);
buf.putInt(bits);
return buf.array();
}
To reverse it:
public static int fromByteArray(byte[] b) {
ByteBuffer buf = ByteBuffer.wrap(b);
return buf.getInt();
}
My first answer would be bitshifting, but on a second thought I think using outputstreams could be better and more simple to understand. I usually avoid casting, but if you're not going for a generic solution I guess that would be okay. :)
Using streams, a generic solution:
public byte[] intToByteArray(final int i) throws java.io.IOException {
java.io.ByteArrayOutputStream b = new java.io.ByteArrayOutputStream();
java.io.DataOutputStream d = new java.io.DataOutputStream(b);
d.writeInt(i);
d.flush();
return b.toByteArray();
}
And to reverse it:
public int byteArrayToInt(final byte[] b) throws IOException {
java.io.ByteArrayInputStream ba = new java.io.ByteArrayInputStream(b);
java.io.DataInputStream d = new java.io.DataInputStream(ba);
return d.readInt();
}
You have to cast to (byte) as default number type in java is int, which is bigger than byte. As long as the value fits in byte it is ok to cast.
Try this:
sendData[0] =(byte)0x26
sendData[1] =(byte)0x94
Or this:
sendData[0] =(byte)38
sendData[1] =(byte)148
You must cast data into byte in order to assign it to a byte!
That does not mean you lost precision, just writing 0x26 means an int to Java compiler..
But also note: range of a byte is from -128 to 127, so in case of 0x94=148 it will be represented after byte casting as '-108' , so it will not work correctly in mathematical computations..
It's because everything in Java is signed. 0x94 (148) is greater than Byte.MAX_VALUE(2^7-1).
What you need is
public static byte[] intToByteArray(int value) {
byte[] b = new byte[4];
for (int i = 0; i < 4; i++) {
int offset = (b.length - 1 - i) * 8;
b[i] = (byte) ((value >>> offset) & 0xFF);
}
return b;
}