Convert 4 Bytes to Int

Convert four bytes to Integer using C++

Your buffer contains signed characters. So, actually, buffer[0] == -29, which upon conversion to int gets sign-extended to 0xffffffe3, and in turn (0x3e << 8) | 0xffffffe3 == 0xffffffe3.

You need ensure your individual buffer bytes are interpreted unsigned, either by declaring buffer as unsigned char *, or by explicitly casting:

int a = int((unsigned char)(buffer[0]) << 24 |
(unsigned char)(buffer[1]) << 16 |
(unsigned char)(buffer[2]) << 8 |
(unsigned char)(buffer[3]));

Converting an int into a 4 byte char array (C)

The portable way to do this (ensuring that you get 0x00 0x00 0x00 0xaf everywhere) is to use shifts:

unsigned char bytes[4];
unsigned long n = 175;

bytes[0] = (n >> 24) & 0xFF;
bytes[1] = (n >> 16) & 0xFF;
bytes[2] = (n >> 8) & 0xFF;
bytes[3] = n & 0xFF;

The methods using unions and memcpy() will get a different result on different machines.


The issue you are having is with the printing rather than the conversion. I presume you are using char rather than unsigned char, and you are using a line like this to print it:

printf("%x %x %x %x\n", bytes[0], bytes[1], bytes[2], bytes[3]);

When any types narrower than int are passed to printf, they are promoted to int (or unsigned int, if int cannot hold all the values of the original type). If char is signed on your platform, then 0xff likely does not fit into the range of that type, and it is being set to -1 instead (which has the representation 0xff on a 2s-complement machine).

-1 is promoted to an int, and has the representation 0xffffffff as an int on your machine, and that is what you see.

Your solution is to either actually use unsigned char, or else cast to unsigned char in the printf statement:

printf("%x %x %x %x\n", (unsigned char)bytes[0],
(unsigned char)bytes[1],
(unsigned char)bytes[2],
(unsigned char)bytes[3]);

Java Convert 4 bytes to int

Depending on where you get those 4 bytes from:

http://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#readInt()

http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#getInt(int)

You can of course still do it manually, but in most cases using one of those (if you have to convert a byte array with lots of bytes, you might want to use a DataInputStream around a ByteArrayInputStream for example) is easier.

Edit: If you need to change the endianness, you will have to use a ByteBuffer, or reverse the bytes yourself, or do the conversion yourself, as DataInput does not support changing the endianness.

Edit2: When you get them from the socket input stream, I'd wrap that one into a DataInputStream and use it for reading all kinds of data. Especially since InputStream.read(byte[]) will not guarantee to fill the whole byte array... DataInputStream.readFully does.

DataInputStream in = new DataInputStream(socket.getInputStream());
byte aByte = in.readByte();
int anInt = in.readInt();
int anotherInt = in.readInt();
short andAShort = in.readShort(); // 11 bytes read :-)
byte[] lotOfBytes = new byte[anInt];
in.readFully(lotOfBytes);

Edit3: When reading multiple times from a stream, they will continue reading where you stopped, i. e. aByte will be byte 0, anInt will be bytes 1 to 4, anotherInt will be bytes 5 to 8, etc. readFully will read on after all that and will block until it has read lotOfbytes.

When the stream stops (the connection drops) you will get EOFException instead of -1, so if you get -1, the int really was -1.

If you do not want to parse any bytes at all, you can skip() them. Parsing one byte in 2 different ways is not possible with DataInputStream (i. e. read first an int from byte 0 to 3, then one from byte 2 to 5), but usually not needed either.

Example:

// read messages (length + data) until the stream ends:
while (true) {
int messageLength;
try {
messageLength = in.readInt(); // bytes 0 to 3
} catch (EOFException ex) {
// connection dropped, so handle it, for example
return;
}
byte[] message = new byte[messageLength];
in.readFully(message);
// do something with the message.
}
// all messages handled.

Hope this answers your additional questions.

Converting 4 bytes to an integer

I'm not sure where you have your error. What you tried works if there are four values.

>>> mybytes = 1,2,3,4
>>> import struct
>>> struct.unpack('i',bytes(mybytes))
(67305985,)
>>> hex(_[0])
'0x4030201'

Convert bytes to int?

Assuming you're on at least 3.2, there's a built in for this:

int.from_bytes( bytes, byteorder, *, signed=False )

...

The argument bytes must either be a bytes-like object or an iterable
producing bytes.

The byteorder argument determines the byte order used to represent the
integer. If byteorder is "big", the most significant byte is at the
beginning of the byte array. If byteorder is "little", the most
significant byte is at the end of the byte array. To request the
native byte order of the host system, use sys.byteorder as the byte
order value.

The signed argument indicates whether two’s complement is used to
represent the integer.

## Examples:
int.from_bytes(b'\x00\x01', "big") # 1
int.from_bytes(b'\x00\x01', "little") # 256

int.from_bytes(b'\x00\x10', byteorder='little') # 4096
int.from_bytes(b'\xfc\x00', byteorder='big', signed=True) #-1024

Convert 4 bytes char to int32 in C

Reverse the order of the a[] indexes, e.g,. a[0] -> a[3]

I think you have the endianness in reverse.

Try this:

a[3] = (num>>24) & 0xFF;
a[2] = (num>>16) & 0xFF;
a[1] = (num>>8) & 0xFF;
a[0] = num & 0xFF;

How to convert last 4 bytes in an array to an integer?

Access the underlying ArrayBuffer and create a new TypedArray with a slice of its bytes:

var u8 = new Uint8Array([1,2,3,4,5,6]); // original array
var u32bytes = u8.buffer.slice(-4); // last four bytes as a new `ArrayBuffer`
var uint = new Uint32Array(u32bytes)[0];

If the TypedArray does not cover the entire buffer, you need to be a little trickier, but not much:

var startbyte = u8.byteOffset + u8.byteLength - Uint32Array.BYTES_PER_ELEMENT;
var u32bytes = u8.buffer.slice(startbyte, startbyte + Uint32Array.BYTES_PER_ELEMENT);

This works in both cases.

If the bytes you want fit in the alignment boundary of your underlying buffer for the datatype (e.g., you want the 32-bit value of bytes 4-8 of the underlying buffer), you can avoid copying the bytes with slice() and just supply a byteoffset to the view constructor, as in @Bergi's answer.

Below is a very-lightly-tested function that should get the scalar value of any offset you want. It will avoid copying if possible.

function InvalidArgument(msg) {
this.message = msg | null;
}

function scalarValue(buf_or_view, byteOffset, type) {
var buffer, bufslice, view, sliceLength = type.BYTES_PER_ELEMENT;
if (buf_or_view instanceof ArrayBuffer) {
buffer = buf_or_view;
if (byteOffset < 0) {
byteOffset = buffer.byteLength - byteOffset;
}
} else if (buf_or_view.buffer instanceof ArrayBuffer) {
view = buf_or_view;
buffer = view.buffer;
if (byteOffset < 0) {
byteOffset = view.byteOffset + view.byteLength + byteOffset;
} else {
byteOffset = view.byteOffset + byteOffset;
}
return scalarValue(buffer, view.byteOffset + byteOffset, type);
} else {
throw new InvalidArgument('buf_or_view must be ArrayBuffer or have a .buffer property');
}
// assert buffer instanceof ArrayBuffer
// assert byteOffset > 0
// assert byteOffset relative to entire buffer
try {
// try in-place first
// only works if byteOffset % slicelength === 0
return (new type(buffer, byteOffset, 1))[0]
} catch (e) {
// if this doesn't work, we need to copy the bytes (slice them out)
bufslice = buffer.slice(byteOffset, byteOffset + sliceLength);
return (new type(bufslice, 0, 1))[0]
}
}

You would use it like this:

// positive or negative byte offset
// relative to beginning or end *of a view*
100992003 === scalarValueAs(u8, -4, Uint32Array)
// positive or negative byte offset
// relative to the beginning or end *of a buffer*
100992003 === scalarValue(u8.buffer, -4, Uint32Array)

Convert 4 bytes to integer using struct

You could convert it to a bytearray and pass that to struct.unpack().

import struct

data = [123, 45, 67, 89]

# Show hex values of data.
print(list('%02x' % b for b in data)) # -> ['7b', '2d', '43', '59']

# Convert to 4 byte unsigned integer data interpreting data as being in
# little-endian byte order.
value = struct.unpack("<I", bytearray(data))[0]
print(hex(value)) # -> 0x59432d7b


Related Topics



Leave a reply



Submit