This question already has answers here:
How to calculate crc16 in php
(2 answers)
Closed 8 years ago.
How to convert the Java CRC16 code to PHP code? PHP doesn't accept byte and >>>
public static int CRC16(final byte[] buffer) {
int crc = 0xffff;
for (int i = 0; i < buffer.length; i++) {
crc = ((crc >>> 8) | (crc << 8)) & 0xffff;
crc ^= (buffer[i] & 0xff);
crc ^= ((crc & 0xff) >> 4);
crc ^= (crc << 12) & 0xffff;
crc ^= ((crc & 0xff) << 5) & 0xffff;
}
crc &= 0xffff;
return crc;
}
Replace crc >>> 8 with (crc >> 8) & 0xff.
Related
I have a function like so:
static int byteArrayToInt(byte[] bytes) {
return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}
Which should convert a byteArray of 4 bytes to an int.
The byte array in hexBinary is:E0C38881
And the expected output should be: 3770910849
But I am getting: -524056447
What do I need to do to fix this?
3770910849 is higher than Integer.MAX_VALUE. If you require a positive value, use long instead of int.
For example :
static long byteArrayToInt(byte[] bytes) {
return (long)((bytes[0] << 24) | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF)) & 0xffffffffL;
}
This is what I used to get it working:
static long getLong(byte[] buf){
long l = ((buf[0] & 0xFFL) << 24) |
((buf[1] & 0xFFL) << 16) |
((buf[2] & 0xFFL) << 8) |
((buf[3] & 0xFFL) << 0) ;
return l;
}
I have a hexBinary of 4 bytes as follows:
FFFFFFC4
It should return something big but the following function just gives -60:
public static int byteArrayToInt(byte[] b)
{
return b[3] & 0xFF |
(b[2] & 0xFF) << 8 |
(b[1] & 0xFF) << 16 |
(b[0] & 0xFF) << 24;
}
Why it doesn't work? Am I doing something wrong?
The primitive type int is 32-bits long and the most significative bit is the sign. The value FFFFFFC4 has the MSB set to 1, which represents a negative number.
You can get "something big" by using long instead of int:
public static long byteArrayToInt(byte[] b)
{
return (((long) b[3]) & 0xFF) |
(((long) b[2]) & 0xFF) << 8 |
(((long) b[1]) & 0xFF) << 16 |
(((long) b[0]) & 0xFF) << 24;
}
I'm aware that java byte is a 8 bits signed variable and to get unsigned (byte) values I will have to do the masking with 0xff everywhere.
Java documentation also says that I can use int to generate unsigned bits by using the procedure previously mentioned.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
However, whether using the mask or not, it returns the same results.
I've trying changing short into int but no success.
Delphi Code
procedure TForm1.ReadHoldRegisters(var lst: TList<byte>; deviceaddr: byte;
RegisterAddress, RegisterLength: word);
begin
lst.Add(deviceaddr);
lst.Add(6);
lst.Add(RegisterAddress div 256);
lst.Add(RegisterAddress mod 256);
lst.Add(RegisterLength div 256);
lst.Add(RegisterLength mod 256);
Add_CRC16(lst);
end;
procedure TForm1.Add_CRC16(var Data: TList<byte>);
var
CRC16Lo, CRC16Hi, CL, CH, SaveHi, SaveLo: byte;
Flag: Integer;
b: byte;
begin
CRC16Lo := $FF;
CRC16Hi := $FF;
CL := $1;
CH := $A0;
for b in Data do
begin
CRC16Lo := CRC16Lo Xor b;
For Flag := 0 To 7 Do
Begin
SaveHi := CRC16Hi;
SaveLo := CRC16Lo;
CRC16Hi := CRC16Hi Div 2;
CRC16Lo := CRC16Lo Div 2;
If ((SaveHi And $1) = $1) Then
begin
CRC16Lo := CRC16Lo Or $80;
end;
If ((SaveLo And $1) = $1) Then
Begin
CRC16Hi := CRC16Hi Xor CH;
CRC16Lo := CRC16Lo Xor CL;
End;
End;
end;
Data.Add(CRC16Lo);
Data.Add(CRC16Hi);
end;
Java Code
public void ReadHoldRegisters(List<Short> lst, byte deviceaddr, char RegisterAddress, char RegisterLength)
{
lst.add((short) (deviceaddr & 0xff));
lst.add((short) ((byte) 6 & 0xff));
lst.add((short) ((RegisterAddress / 256 & 0xff)));
lst.add((RegisterAddress%256));
lst.add((RegisterLength/256));
lst.add(((RegisterLength%256)));
Add_CRC16(lst);
}
private void Add_CRC16(List<Short> Data)
{
//Cyclic Redundancy Check 16
short SaveLo, SaveHi;
int flag;
short CRC16Lo = ((short) 0xFF & 0xff);
short CRC16Hi = ((short) 0xFF & 0xff);
short CL = (short) 0x1 & 0xff;
short CH = (short) (0xA0) & 0xff;
short andop = ((short) 0x80 & 0xff);
short andop2 = (short) 0x1 & 0xff;
// inĂcio do for in
for (Short b : Data)
{
CRC16Lo ^= b & 0xff;
for(flag=0;flag<7;flag++)
{
SaveHi = (short) ((CRC16Hi) & 0xff);
SaveLo = (short) ((CRC16Lo) & 0xff);
CRC16Hi = (short) ((CRC16Hi/2) & 0xff);
CRC16Lo = (short) ((CRC16Lo/2) & 0xff);
if((SaveHi & andop2) == andop2 )
CRC16Lo |= andop & 0xff;
if(((SaveLo) & (andop2)) == (andop2))
{
CRC16Hi ^= CH & 0xff;
CRC16Lo ^= CL & 0xff;
}
}
}
Data.add((short) (CRC16Lo & 0xff));
Data.add((short) (CRC16Hi & 0xff));
}
The correct result to be displayed in this case is "01 06 00 01 00 0A 58 0D"
Any thoughts? Any help?
The most obvious difference is here:
for(flag=0;flag<7;flag++)
This loops runs one fewer times than the Delphi version. You mean:
for(flag=0;flag<8;flag++)
On top of that, the Java code was needlessly complex. It can be greatly simplified. This program gives the same output as the Delphi code:
import java.util.*;
public class test
{
public static void ReadHoldRegisters(List<Integer> lst, int deviceaddr, int RegisterAddress, int RegisterLength)
{
lst.add(deviceaddr & 0xff);
lst.add(6);
lst.add((RegisterAddress >> 8) & 0xff);
lst.add(RegisterAddress & 0xff);
lst.add((RegisterLength >> 8) & 0xff);
lst.add(RegisterLength & 0xff);
Add_CRC16(lst);
}
private static void Add_CRC16(List<Integer> Data)
{
int SaveLo, SaveHi;
int CRC16Lo = 0xFF;
int CRC16Hi = 0xff;
int CL = 0x1;
int CH = 0xA0;
for (int b : Data)
{
CRC16Lo ^= b;
for (int flag=0; flag<8; flag++)
{
SaveHi = CRC16Hi;
SaveLo = CRC16Lo;
CRC16Hi = CRC16Hi/2;
CRC16Lo = CRC16Lo/2;
if((SaveHi & 0x01) == 0x01)
CRC16Lo |= 0x80;
if((SaveLo & 0x01) == 0x01)
{
CRC16Hi ^= CH;
CRC16Lo ^= CL;
}
}
}
Data.add(CRC16Lo & 0xff);
Data.add(CRC16Hi & 0xff);
}
public static void main(String[] args)
{
List<Integer> lst = new ArrayList<Integer>();
ReadHoldRegisters(lst, 1, 1, 10);
for (int value: lst)
{
System.out.print(String.format("%02x", value));
System.out.print(" ");
}
}
}
This question already has answers here:
Byte Array and Int conversion in Java
(10 answers)
Closed 8 years ago.
I have a method that converts int to byte[]
private static byte[] intToBytes(int i)
{
byte[] integerBs = new byte[MAX_INT_LEN];
integerBs[0] = (byte) ((i >>> 24) & 0xFF);
integerBs[1] = (byte) ((i >>> 16) & 0xFF);
integerBs[2] = (byte) ((i >>> 8) & 0xFF);
integerBs[3] = (byte) (i & 0xFF);
return integerBs;
}
Let's say I try to convert the integer 4 to bits:
byte[] lenBs = intToBytes(4);
int a=(int)lenBs[0];
System.out.println("result:"+a);
The value of MAX_INT_LENGTH is 4
I get result:0 for every int that I put as a parameter for the method.Please tell me where i went wrong.Thank you.
lenBs[0] is just getting:
integerBs[0] = (byte) ((i >>> 24) & 0xFF);
... which in the case of i = 4, integerBs[0] == 0.
I'm trying to mask an integer in order to separate each byte individually like so:
int a = (0xffffffff & 0xff000000) >> 24;
int b = (0xffffffff & 0x00ff0000) >> 16;
int c = (0xffffffff & 0x0000ff00) >> 8;
int d = 0xffffffff & 0x000000ff;
b, c and d give the correct answer in this case, 255, however, a continues to give me -1 and other negative numbers no matter what I change it to, I even tried:
int a = (0xefffffff & 0xff000000) >> 24;
and it gives me -17.
Does someone know how do I solve this problem so that in this boundary case a gives me 255 and other positive numbers?
This is because of sign extension. If the top-most bit is 1, then >> shifts in 1s. This is to preserve the sign of the argument. You want to use >>> which always shifts in 0. Or, mask after the shift:
int a = (0xffffffff >> 24) & 0x000000ff;
You are doing a signed shift, so the sign is preserved.
int a = (0xffffffff & 0xff000000) >>> 24; // unsigned shift.
or
int a = 0xffffffff >>> 24; // unsigned shift and all the bottom bits are lost anyway
int b = (0xffffffff >>> 16) & 0xFF;
int c = (0xffffffff >>> 8) & 0xFF;
int d = 0xffffffff & 0xFF;
I think you need an unsigned shifting,
Try it this way...
(0xffffffff & 0xff000000) >>> 24