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. Ifbyteorder
is"big"
, the most significant byte is at the
beginning of the byte array. Ifbyteorder
is"little"
, the most
significant byte is at the end of the byte array. To request the
native byte order of the host system, usesys.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
How to Do If-Else in Thymeleaf
What Does It Mean When They Say Http Is Stateless
How to Abort a Thread in a Fast and Clean Way in Java
Cannot Find Main Class in File Compiled with Ant
How to Check If a Url Exists or Returns 404 with Java
How to Make Line Animation Smoother
Openjdk Availability for Windows Os
How to Write Our Own Iterator in Java
Java: Object to Byte[] and Byte[] to Object Converter (For Tokyo Cabinet)
How to Clear or Empty a Stringbuilder
Pick a Random Value from an Enum
Java.Lang.Noclassdeffounderror: Could Not Initialize Class Xxx
Why We Shouldn't Make a Spring MVC Controller @Transactional
Why Static Fields Are Not Initialized in Time
How to Obtain the Last Path Segment of a Uri