Let me start to say that I have no knowledge at all of Delphi...
I'm trying to port an old app written in delphi to java, but things aren't working...
I have this function that does some binary operation to two bytes. Here's the code in Delphi:
function TMainForm.mixthingsup(x, y: byte): word;
var
counter: byte;
answer1, answer2: byte;
begin
answer1 := $9D xor x;
for counter := 1 to 8 do
begin
if (answer1 and $80) = $80 then
answer1 := (answer1 shl 1) xor $26
else
answer1 := (answer1 shl 1);
end;
answer2 := answer1 xor y;
for counter := 1 to 8 do
begin
if ((answer2 and $80) = $80) then
answer2 := ((answer2 shl 1) xor $72)
else
answer2 := (answer2 shl 1);
end;
Result := (answer1 shl 8) or answer2;
end;
And here's my java code:
public static String mixthingsup(String data)
{
byte[] conv=null;
byte c9d;
byte c80;
byte c26;
byte c72;
byte x,y;
byte res1, res2;
byte res;
conv=hexStringToByteArray(data.substring(0, 2));
x=conv[0];
conv=hexStringToByteArray(data.substring(2, 4));
y=conv[0];
conv=hexStringToByteArray("9d");
c9d=conv[0];
conv=hexStringToByteArray("80");
c80=conv[0];
conv=hexStringToByteArray("26");
c26=conv[0];
conv=hexStringToByteArray("72");
c72=conv[0];
res1=(byte) (c9d ^ x);
for(int i=1; i<9; i++)
{
if((res1 & c80) == c80)
res1=(byte) ((res1 << 1) ^ c26);
else
res1=(byte) (res1 << 1);
}
res2=(byte) (res1 ^ y);
for(int i=1; i<9; i++)
{
if((res2 & c80) == c80)
res2=(byte) ((res2 << 1) ^ c72);
else
res2=(byte) (res2 << 1);
}
res=(byte) ((res1 << 8) | res2);
return Integer.toHexString(res);
}
When the delphi function returns CA BA for A8 77, for instance, the java function returns FF FF FF BA
Any thoughts? Any help?
Thanks,
Pedro
Look at this line:
res=(byte) ((res1 << 8) | res2);
When you cast it to byte you are truncating a 16 bit value into 8 bits and so lose res1.
You should cast to a 2 byte value, short.
That said, it might be easier just to return your two bytes in an array. Like this:
public static byte[] MixThingsUp(byte x, byte y)
{
byte answer1 = (byte) (0x9D ^ x);
for (int i=0; i<8; i++)
if ((answer1 & 0x80) == 0x80)
answer1 = (byte) ((answer1 << 1) ^ 0x26);
else
answer1 = (byte) (answer1 << 1);
byte answer2 = (byte) (answer1 ^ y);
for (int i=0; i<8; i++)
if ((answer2 & 0x80) == 0x80)
answer2 = (byte) ((answer2 << 1) ^ 0x72);
else
answer2 = (byte) ((answer2 << 1));
return new byte[] { answer1, answer2 };
}
If I were you I would separate the bitwise manipulations and the conversions to and from string. The way you have it in your question mixes the two concerns.
Related
I want to create an app that can open binary file, read and edit it's content in decimal values, and then save it back to binary file.
This file that I want to open have multiple parameters written in 2 bytes. e.g. 00 06 00 50 01 AB = 6, 80, 427
So far I managed to open bin file, put all data from file into byte[].
Here is the code to open and read file:
String path = getFilesDir().getAbsolutePath();
File file = new File(path + "/file.bin");
int size = (int) file.length();
byte[] bytes = new byte[size];
FileInputStream fis = new FileInputStream(file);
try {
fis.read(bytes);
...
} finally {
fis.close();
}
Here is first attempt to convert byte[] into deciaml values:
for (int i = 0; i < size / 2; i = i + 2) {
intArray[i] = ((bytes[i] & 0xff) << 8) | (bytes[i + 1] & 0xff);
}
But in this code only every second value is correct. It's shows 6,0,80,0,1 and should be 6,80,1.
The second idea was to convert byte[] into String[] and then into e.g. int[] but It doesn't work as intended. In this fragment I didn't parse whole array, but only hexArray[4] which was 50 in hex and 80 in dec, but the result was 50.
for (int i = 0; i < size; i = i + 2) {
num1 = String.format("%02X", bytes[i] & 0xFF);
num2 = String.format("%02X", bytes[i + 1] & 0xFF);
String twoByte = num1 + num2;
hexArrayWithNull[i] = twoByte;
}
String[] hexArray = Arrays.stream(hexArrayWithNull).filter(Objects::nonNull).toArray(String[]::new);
num = String.format("%d", Integer.parseInt(hexArray[4]));
I'm quite stuck here and need some guidance. I must say also that I'm new in programming.
Thanks
You increment i in each iteration by 2 and you store in intArray[i]. So, you store in index [0] then index [2] then index [4] and so on. This explains the zeros at odd indices [1], [3], ...
Also, you must continue the loop until size, not size/2.
Here is the correct loop:
for (int i = 0; i < size; i = i + 2) {
intArray[i/2] = ((bytes[i] & 0xff) << 8) | (bytes[i + 1] & 0xff);
}
Here is the another possibility:
for (int i = 0; i < size/2; i = i + 1) {
intArray[i] = ((bytes[2*i] & 0xff) << 8) | (bytes[2*i + 1] & 0xff);
}
[EDIT]
The reverse operation would be:
for (int i = 0; i < size/2; i = i + 1) {
bytes[2*i] = (intArray[i] & 0xff00) / 256; //or >>8 instead of /256
bytes[2*i+1] = intArray[i] & 0xff;
}
I am trying to understand an implementation of a b+ Tree. I don't understand what this overloaded method exactly do. Why in the first method having Inputsteam is as an argument declare 4 variables which are i1,i2,i3 and i4. In the second method using ObjectInput in as an argument, i understand that it returns a byte from 0 to 255, why is result=251? It will be helpful to explain each line and what it do.
First method:
public final static int readLuposInt(final InputStream is) throws IOException {
final int i1 = is.read();
if (i1 < 0) {
return i1;
}
final int i2 = is.read();
if (i2 < 0) {
return i2;
}
final int i3 = is.read();
if (i3 < 0) {
return i3;
}
final int i4 = is.read();
if (i4 < 0) {
return i4;
}
return (0xFF & i1) | ((0xFF & i2) | ((0xFF & i3) | (0xFF & i4) << 8) << 8) << 8;
}
overloaded method:
public final static int readLuposInt(final ObjectInput in) throws IOException {
final int i0 = in.read();
if (i0 <= 251){
return i0;
}
int result = 251;
int offset = 1;
for (int i = 1; i <= i0 - 251; i++) {
result += in.read() * offset;
offset <<= 8;
}
return result;
}
You could have used a debugger to find the following result.
The first method reads an 4 byte integer from an input stream. It seems to be stored as little-endian value.
the bytes are read in sequentially
ff any of the bytes is missing, -1 is returned.
to return the complete integer, a computation is made by shifting the more significant bytes to the left.
Example:
The number 2293742 represents the hex number 22 FF EE, which will be stored in reverse order: 0xEE 0xFF 0x22 0x00
now the data gets read
i1 = 0xEE
i2 = 0xFF
i3 = 0x22
i4 = 0x00
now the return value is computed:
(0xFF & i4) << 8 = (0xFF & 0x00) << 8 = 0x0000
((0xFF & i3) | (0xFF & i4) << 8) << 8) = ((0x22 | 0x0000) << 8) = (0x0022 << 8) = 0x002200
((0xFF & i2) | ((0xFF & i3) | (0xFF & i4) << 8) << 8) << 8 = (0xFF | 0x002200) << 8 = 0x0022FF00
(0xFF & i1) | ((0xFF & i2) | ((0xFF & i3) | (0xFF & i4) << 8) << 8) << 8 = 0xEE | 0x0022FF00 = 0x0022FFEE
The second method reads unicode characters from the stream, encoded in an UTF-8 encoding. Much can be said about unicode and their character encodings, see Wikipedia how that is working.
So I'm trying to understand base64 encoding better and I came across this implementation on wikipedia
private static String base64Encode(byte[] in) {
StringBuffer out = new StringBuffer((in.length * 4) / 3);
int b;
for (int i = 0; i < in.length; i += 3) {
b = (in[i] & 0xFC) >> 2;
out.append(codes.charAt(b));
b = (in[i] & 0x03) << 4;
if (i + 1 < in.length) {
b |= (in[i + 1] & 0xF0) >> 4;
out.append(codes.charAt(b));
b = (in[i + 1] & 0x0F) << 2;
if (i + 2 < in.length) {
b |= (in[i + 2] & 0xC0) >> 6;
out.append(codes.charAt(b));
b = in[i + 2] & 0x3F;
out.append(codes.charAt(b));
} else {
out.append(codes.charAt(b));
out.append('=');
}
} else {
out.append(codes.charAt(b));
out.append("==");
}
}
return out.toString();
}
And I'm following along and I get to the line:
b = (in[i] & 0xFC) >> 2;
and I don't get it...why would you bitwise and 252 to a number then shift it right 2...wouldn't it be the same if you just shifted the byte itself without doing the bitwise operation? example:
b = in[i] >> 2;
Say my in[i] was the letter e...represented as 101 or in binary 01100101. If I shift that 2 to the right I get 011001 or 25. If I bitwise & it I get
01100101
11111100
--------
01100100
but then the shift is going to chop off the last 2 anyway...so why bother doing it?
Can somebody clarify for me please. Thanks.
IN in[i] >> 2, in[i] is converted to an int first. If it was a negative byte (with the high bit set) it will be converted to a negative int (with the now-highest 24 bits set as well).
In (in[i] & 0xFC) >> 2, in[i] is converted to an int as above, and then & 0xFC makes sure the extra bits are all reset to 0.
You're partially right, in that (in[i] & 0xFF) >> 2 would give the same result. & 0xFF is a common way to convert a byte to a non-negative int in the range 0 to 255.
The only way to know for sure why the original developer used 0xFC, and not 0xFF, is to ask them - but I speculate that it's to make it more obvious which bits are being used.
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(" ");
}
}
}
I've got a long variable and I need to reverse its byte order. For example: B1, B2, ... , B8 I should return a long that consists of B8, B7, ..., B1. How can I do it by using bitwise operations?
you can use Long.reverseBytes(long)
Or for more methods which include bitwise operations, you can refer to this stack overflow question
Heres another method you may like, I'd still recommend the above but it's better than bitwise where you can easily make mistakes.
Bytebuffer
byte[] bytes = ByteBuffer.allocate(8).putLong(someLong).array();
for (int left = 0, right = bytes.length - 1; left < right; ++left, --right) {
byte temp = bytes[left];
bytes[left] = bytes[right];
bytes[right] = temp;
}
I am trying to steer you away from bitwise solutions because they are cumbersome and very easy to mess up if you do not know what you are doing... But bitwise would look like this:
byte[] bytes = new byte[8];
// set the byte array from smallest to largest byte
for(int i = 0; i < 8; ++i) {
byte[i] = (your_long >> i*8) & 0xFF;
}
// build the new long from largest to smallest byte (reversed)
long l = ((buf[0] & 0xFFL) << 56) |
((buf[1] & 0xFFL) << 48) |
((buf[2] & 0xFFL) << 40) |
((buf[3] & 0xFFL) << 32) |
((buf[4] & 0xFFL) << 24) |
((buf[5] & 0xFFL) << 16) |
((buf[6] & 0xFFL) << 8) |
((buf[7] & 0xFFL) << 0) ;
You might want to use Long.reverseBytes instead of using bitwise operations. See the Java Reference for details.
Otherwise, you could have a look at the JDK sources (src.zip in your JDK folder) in Long.java but mind the copyright by Oracle.
Here's an old trick that you can use to endian swap a register:
static long swapblock(long a, long mask, int shift) {
long b1 = a & mask; // extract block
long b2 = a ^ b1; // extract remaining bits
return (b1 << shift) |
((b2 >> shift) & mask); // mask again to clear sign extension
}
static long endianswap(long a) {
a = swapblock(a, 0x00000000ffffffffL, 32);
a = swapblock(a, 0x0000ffff0000ffffL, 16);
a = swapblock(a, 0x00ff00ff00ff00ffL, 8);
return a;
}
The idea is to progressively swap sub blocks until you reach the desired level you want to stop at. By adding swaps of sizes 4, 2, and 1, you can change this into a bit mirror function.
There is only one tricky bit due to lack of unsigned types in java. You need to mask out high order bits when shifting right, because the sign bit is replicated by the shift amount, filling the high order bits with ones (0x8000000000000000 >> 8 is 0xFF80000000000000).
long reverse(long x){
x = (x >> 32) | (x << 32); // step 1
x = ((x & 0xffff0000ffff0000 ) >> 16)
| ((x & 0x0000ffff0000ffff ) << 16); // step 2
x = ((x & 0xff00ff00ff00ff00 ) >> 8)
| ((x & 0x00ff00ff00ff00ff ) << 8); // step 3
return x;
}
If we assume that bitwise operator works in O(1) time, reverse function works in O(lg(number of bits) ) time.
Explanation
Step 0 : B1 B2 B3 B4 B5 B6 B7 B8
Step 1 : B5 B6 B7 B8 B1 B2 B3 B4
Step 2 : B7 B8 B5 B6 B3 B4 B1 B2
Step 3 : B8 B7 B6 B5 B4 B3 B2 B1
Plain answer with loops:
public static long byteReverse(long a) {
long result = 0;
for(int i = 0; i < 8; i++){
// grab the byte in the ith place
long x = (a >> (i*8)) & (0b11111111);
result <<= 8;
result |= x;
}
return result;
}
bitwise only:
public static long byteReverse(long a) {
a = (a << 32) | (a >>> 32);
a = ((a & 0xffff0000ffff0000L) >>> 16) | ((a & 0x0000ffff0000ffffL) << 16);
a = ((a & 0x00ff00ff00ff00ffL) << 8) | ((a & 0xff00ff00ff00ff00L) >>> 8);
return a;
}