Changing bits in bytes in java

So, I understand how to change a single bit in a byte, I'm not sure why my specific code is not working.

public static void setBit(byte[] input, int position, int value) { int byteLocation = position / 8; int bitLocation = position % 8; byte tempByte = input[byteLocation]; if (value == 0) tempByte = (byte) (tempByte & ~(1 << bitLocation)); else tempByte = (byte) (tempByte | (1 << bitLocation)); input[byteLocation] = tempByte; } 

Now I tested it with the string "Testing1" 64 bits long, and then tried to set the bits and display the value. It works with processing up to 46 bits, and then on the 47th bit, if I try to set it to 1, it accelerates, it works fine from 0.

Unable to see the error in my ways, this is how I test it

 String test = "Testing1"; byte[] bytes = test.getBytes(); for (int i = 0; i < bytes.length; i++) System.out.print(String.format("%8s", Integer.toBinaryString(bytes[i])).replace(' ', '0') + "[" + i + "] "); setBit(bytes, 44, 1); System.out.println(); for (int i = 0; i < bytes.length; i++) System.out.print(String.format("%8s", Integer.toBinaryString(bytes[i])).replace(' ', '0') + "[" + i + "] "); 

Below is the result when I try to change the 47th bit to 1

 01010100[0] 01100101[1] 01110011[2] 01110100[3] 01101001[4] 01101110[5] 01100111[6] 00110001[7] 01010100[0] 01100101[1] 01110011[2] 01110100[3] 01101001[4] 11111111111111111111111111101110[5] 01100111[6] 00110001[7] 
+4
source share
5 answers

Change formatting as

 Integer.toBinaryString(0xFF & bytes[i]) 
Byte

should be masked as it is expanded with extension, not with zero extension, to 32-bit int

+3
source

The problem is that you are setting the character bit in the specified byte. So this byte now has a negative value. You call Integer.toBinaryString() , which takes an int as an argument, not a byte. The byte receives the value before int and correctly evaluates the value:

 11101110 

an equivalent integer to it:

 11111111111111111111111111101110 
+2
source

I reduced your method with ^ (xor)

 public static void setBit(byte[] input, int position, int value) { int byteLocation = position / 8; int bitLocation = position % 8; input[byteLocation] = (byte) (input[byteLocation] ^ (byte) (1 << bitLocation)); } 
0
source

I did not examine it in too much detail, but I think the problem with one bite is that it extends to int (since it is signed, 1 extends to negative int).

Just take the last 8 characters of the string and it will work fine.

0
source

I recently had to do something similar.
I managed to achieve this (a lot of use of the board, but ...) by shifting the source bits directly to the LSB position that I wanted to replace, and doing all the bits, including the MSB I wanted to replace, 1.
Then I AND'yielded the bit that I want instead of the bit I want to replace, shifted to the left, the same number that I shifted to the right, OR'ing the result with the original and AND'ed using the XOR'ed replacement mask. (Take a breath, I'll try to explain)

Say I have bytes:
1111 1010 0001 1001

and I want to replace piece 1010 with 0001 in order to produce:

1111 0001 0001 1001.

To achieve this, I performed the following steps:

1) Move right to 8 to produce:
0000 0000 1111 1010

2) OR mask 0xf (1111) to create:
0000 0000 1111 1111

3) And replacing 0001 with 0000 0000 1111 1111 for production:
0000 0000 0000 0001

4) Left shift by 8 to create:
0000 0001 0000 0000

5) Move the mask from LSB and XOR with full bytes

1111 1111 1111 1111
0000 1111 0000 0000
===================
1111 0000 1111 1111

6) And XOR'ed, shifted mask with the original to create:

1111 0000 0001 1001
1111 0000 1111 1111
===================
1111 0000 0001 1001

7) OR that the result of the above with a replacement:

1111 0000 0001 1001
0000 0001 0000 0000
===================
1111 0001 0001 1001 < final result
===================


In java, this leads to a function:

 public long overwriteBits(long overwrite, long with, long shift, long mask) { return ((((overwrite >> shift) | mask) & with) << shift) | (overwrite & (~0 ^ (mask << shift))); } 

If โ€œoverwriteโ€ is the source data, โ€œcโ€ is the bit that you want instead of the bits in the โ€œshiftโ€ position, and the mask is a series of positive bits with the same replacement length.

To do this, I will call (in sudo):
overwriteBits (1111 1010 00011001, 0001 , 8, 1111)

I want to mention that the above will work to replace bits in any primitive, without the need for byte arrays. e.g. 11 bit replacement as below:

1101001010101101 1111 0101 101 001101
s 1010 1010 101

overwriteBits (1101001010101101 1111 0101 101 001101 , 1010 1010 101, 6 , 11111111111)

1101001010101101 1111 0101 101 001101
110 100 110 110 101 101 1010 101 101 00101

overwriteBits (1789785421l, 1365l, 6, 0x7FF)

0
source

All Articles