I am aware that a similar question has already been asked before (see How to read a single bit buffer in node), but it seems none of the answers are helful. The first comment that has been accepted, stating to use buf.readUIntLE()
, is not working since 2 arguments are expected, but 0 was provided.
Thus, I am currently trying to read a single bit (the 17th one) from a Buffer, but I can't find a way to easily read it. I have been using buffer.readUInt16BE(0)
to read the 2 first bytes of the Buffer and so far it works fine, but I need to assign the 17th bit to a variable.
Note: My Buffer data is Big-Endian and I am coding in TypeScript.
I thought about doing something like:
const myVar: number = parseInt(buffer.readUIntBE(2, 1).toString().slice(0,1));
in order to read, then stringify the 3th byte, then getting the first caracter and convert it into a number, but I find it very clunky.
Is there a simple way to achieve this ?
UPDATE
I finally decided to create myself a small utility function to read a specific bit in a Buffer/UInt8Array that seems to do the job pretty well. Note: Byte are always read from left to right and bits are read from left to right. That comes handy when using the function.
/**
* @name readBit()
* @brief Allows to read the value of a bit in a buffer by specifying from which byte to read the specified bit.
* @param buffer The Buffer/UInt8Array to read the bit from.
* @param index The zero-based cardinal index of the byte to read the bit from.
* @param bit The zero-based cardinal index of the bit to read from the byte.
* @return The bit value.
*/
export function readBit(buffer: Buffer, index: number, bit: number): number {
return (buffer[index] >> bit) & 1;
}
export default readBit;
If you want the function to be more intuitive, and to specify the zero-based index from left to right of bits, the function must be modified to this instead:
/**
* @name readBit()
* @brief Allows to read the value of a bit in a buffer by specifying from which byte to read the specified bit.
* @param buffer The Buffer/UInt8Array to read the bit from.
* @param byteIndex The zero-based cardinal index of the byte to read the bit from. Bytes reading is from right to left.
* @param bitIndex The zero-based cardinal index of the bit to read from the byte. Bits reading is from left to right.
* @return The bit value.
*/
export function readBit(buffer: Buffer, byteIndex: number, bitIndex: number): number {
return (buffer[byteIndex] >> 7 - bitIndex) & 1;
}
export default readBit;
Thanks a lot to @Bergi for his help with this.
A buffer is also a Uint8Array
typed array, you can simply access its bytes by index. (If you prefer to do it with a method call, the equivalent would be readUint8
). Then simply access the respective bit in that byte:
const position = 17;
const bitOffset = position & 7; // in byte
const byteIndex = position >> 3; // in buffer
const bit = (buffer[byteIndex] >> bitOffset) & 1;
(Regarding the numbers: there are 8
= 2³
bits in a byte, and 7
is (1<<3)-1
or 0b111
)
If you subscribe to MSB 0 bit numbering, as is used in most network protocols, you will however have to do
const bit = (buffer[byteIndex] >> (7 - bitOffset)) & 1;