This question already has answers here:
Why does BinaryReader.ReadUInt32() reverse the bit pattern?
(6 answers)
Closed 9 years ago.
I am trying to read a binary file in C#, but I am facing a problem.
I declared the following:
public static readonly UInt32 NUMBER = 0XCAFEBABE;
Then while reading from the very beginning of the file I am asking to read the first 4 bytes (already tried different ways, but this is the simplest):
UInt32 num = in_.ReadUInt32(); // in_ is a BinaryReader
While I have that the 4 bytes are CA, FE, BA and BE (in hex) while convert them to UInt I am getting different values. NUMBER is 3405691582, num is 3199925962.
I also tried to do this:
byte[] f2 = {0xCA, 0xFE, 0xBA, 0xBE};
and the result of doing BitConverter.ToUInt32(new byte[]{0xCA, 0xFE, 0xBA, 0xBE},0) is 3199925962.
can anyone help me?
This is because of the little endianness of your machine. See BitConverter.IsLittleEndian property to check this.
Basically, numbers are stored in reverse byte order, compared to how you would write them down. We write the most significant number on the left, but the (little endian) PC stores the least significant byte on the left. Thus, the result you're getting is really 0xBEBAFECA (3199925962 decimal) and not what you expected.
You can convert using bit shifting operations:
uint value = (f2[0] << 24) | (f2[1] << 16) | (f2[2] << 8) | f2[3];
There are many more ways to convert, including IPAddress.NetworkToHostOrder as I4V pointed out, f2.Reverse(), etc.
For your specific code, I believe this would be most practical:
uint num = (uint)IPAddress.NetworkToHostOrder(in_.ReadInt32());
This may result in an arithmetic underflow however, so it may cause problems with a /checked compiler option or checked keyword (neither are very common).
If you want to deal with these situations and get even cleaner code, wrap it in an extension method:
public static uint ReadUInt32NetworkOrder(this BinaryReader reader)
{
unchecked
{
return (uint)IPAddress.NetworkToHostOrder(reader.ReadInt32());
}
}
That's what is called byte order:
var result1 = BitConverter.ToUInt32(new byte[] { 0xCA, 0xFE, 0xBA, 0xBE }, 0);
//3199925962
var result2 = BitConverter.ToUInt32(new byte[] { 0xBE, 0xBA, 0xFE, 0xCA }, 0);
//3405691582
Related
My I need to generate a random 32 char HEX string. I have code in place that will generate for example E272E28B8961FB155E3FC657831F0690
Now, I need to break this down into two 32 char strings such that value of string 1 XOR string 2 will = E272E28B8961FB155E3FC657831F0690
I seem to be having a hard time wrapping my head around that. I suppose I need a reverse XOR on this string. Any suggestions on how to accomplish this?
Assuming that you want two 32 Hexadecimal Character strings (which is equivalent to 16 bytes) which will XOR to a known 32 Hexadecimal Character string, you can use this method.
Generate random bytes for the first part of the output, then calculate what the second part has to be based on the first part and the expected output. XOR is a self-inverting operator (there's a fancy word for that that I'm forgetting) so it's fairly straightforward to do.
void q50415070()
{
var random = new Random();
var output = new byte[16];
random.NextBytes(output);
Debug.WriteLine(BitConverter.ToString(output));
// 91-77-E9-2F-EC-F7-8E-CC-03-AF-37-FD-4F-6F-D2-4D
var part1 = new byte[16];
random.NextBytes(part1);
Debug.WriteLine(BitConverter.ToString(part1));
// 7A-9B-2B-8B-D7-CE-AA-7E-7E-C3-FE-FF-44-2A-21-3C
var part2 = part1.Zip(output, (x, y) => (byte)(x ^ y)).ToArray();
Debug.WriteLine(BitConverter.ToString(part2));
// EB-EC-C2-A4-3B-39-24-B2-7D-6C-C9-02-0B-45-F3-71
}
In this, output is the result I'm trying to reach, and part1 and part2 are the two components that I want to be able to XOR together to get the expected output.
I've used the Linq Zip method to combine the two IEnumerable<byte>s together element by element, then used the XOR operator ^ to calculate the result byte-by-byte. Finally calling ToArray() to make it back into an array at the end.
This technique is used often in cryptography where you want to split an encryption key into two parts for two people to have, each of which is useless by itself.
Edit: Tweaked the function slightly to more closely match your question:
void q50415070()
{
var output = new byte[16] { 0xE2, 0x72, 0xE2, 0x8B, 0x89, 0x61, 0xFB, 0x15, 0x5E, 0x3F, 0xC6, 0x57, 0x83, 0x1F, 0x06, 0x90 };
Debug.WriteLine(BitConverter.ToString(output));
// E2-72-E2-8B-89-61-FB-15-5E-3F-C6-57-83-1F-06-90
var random = new Random();
var part1 = new byte[16];
random.NextBytes(part1);
Debug.WriteLine(BitConverter.ToString(part1));
// 59-37-D0-A6-71-CC-6C-17-96-02-70-CE-A7-57-06-25
var part2 = part1.Zip(output, (x, y) => (byte)(x ^ y)).ToArray();
Debug.WriteLine(BitConverter.ToString(part2));
// BB-45-32-2D-F8-AD-97-02-C8-3D-B6-99-24-48-00-B5
}
Hope this helps
I apologize in advance if my question is not clear enough, I don't have a lot of experience with c# and I encounter an odd problem.
I am trying to convert an int into an array of two bytes (for example: take 2210 and get: 0x08, 0xA2), but all I'm getting is: 0x00, 0xA2, and I can't figure out why. Would highly appreciate any advice.
(I've tried reading other questions regarding this matter, but couldn't find an helpful answer)
my code:
profile_number = GetProfileName(); // it gets the int
profile_num[0] = (byte) ((profile_number & 0xFF00));
profile_num[1] = (byte) ((profile_number & 0x00FF));
profile_checksum = CalcProfileChecksum();
//Note: I'm referring to a 2-byte array, so the answer to the question regarding 4-byte arrays does not help me.
You need to shift the 1st byte:
//profile_num[0] = (byte) ((profile_number & 0xFF00));
profile_num[0] = (byte) ((profile_number & 0xFF00) >> 8);
profile_num[1] = (byte) ((profile_number & 0x00FF));
First I thought that this is the simplest way:
public static byte[] IntToByteArray(int value)
{
return (new BigInteger(value)).ToByteArray();
}
But i realised that ToByteArray returns only needed bytes. If the value is small (under 256) then a single byte will be returned. Another thing that I noticed is that values are reversed in the returned array so that the byte that is in the right (the most insignificant byte) is found in the left. So I come with a little revision:
public static byte[] IntToByteArrayUsingBigInteger(int value, int numberOfBytes)
{
var res = (new BigInteger(value)).ToByteArray().Reverse().ToArray();
if (res.Length == numberOfBytes)
return res;
byte[] result = new byte[numberOfBytes];
if (res.Length > numberOfBytes)
Array.Copy(res, res.Length - numberOfBytes, result, 0, numberOfBytes);
else
Array.Copy(res, 0, result, numberOfBytes - res.Length, res.Length);
return result;
}
I know that this does not compare with the performance of having bitwise operations but for the sake of learning new things and if you prefeer to use high level classes that .NET provides instead of going low level and use bitwise operators i think it's a nice alternative.
I try to convert an Ip Address to a long value :
byte[] Ip = new byte[4] { 192, 168, 1, 0 };
UInt32 Ret1 = (((UInt32)Ip[0]) << 24) |
(((UInt32)Ip[1]) << 16) |
(((UInt32)Ip[2]) << 8) |
(((UInt32)Ip[3]));
UInt32 Ret2 = BitConverter.ToUInt32(Ip, 0);
Ret1 returns 3232235776 (the correct value)
Ret2 returns 108736 (?)
Why this difference ?
Indeed, endianness is your issue here. While not difficult to work around, it can be annoying at times on Intel-based systems due to them being in Little Endian whereas Network Order is Big Endian. In short, your bytes are in the reverse order.
Here is a little convenience method you may use to solve this issue (and even on various platforms):
static uint MakeIPAddressInt32(byte[] array)
{
// Make a defensive copy.
var ipBytes = new byte[array.Length];
array.CopyTo(ipBytes, 0);
// Reverse if we are on a little endian architecture.
if(BitConverter.IsLittleEndian)
Array.Reverse(ipBytes);
// Convert these bytes to an unsigned 32-bit integer (IPv4 address).
return BitConverter.ToUInt32(ipBytes, 0);
}
Sounds like you have a problem with endianness.
http://en.wikipedia.org/wiki/Endianness
The platform (bitness) independent code can looks lake this:
UInt32 Ret2 = BitConverter.ToUInt32(
BitConverter.IsLittleEndian
? Ip.Reverse().ToArray()
: Ip, 0);
It's an endian issue. IPAddress.HostToNetworkOrder has various overloads for converting numeric types to their network equivilant (ie little endian to big endian).
IP addresses are typically written in Network Byte Order which happens to be the other endianness of standard x86.
Google for aton(), ntoa() and big endian.
So I have a Delphi application that is taking records of various types, throwing them on a memorystream via stream.Write(record, sizeof(record)) and sending them over a named pipe.
Take this Delphi record :
Type TAboutData = record
Version : array[0..4] of Byte;
Build : Word;
BuildDate : TDateTime;
SVNChangeset : Word;
end;
When this is sent over the named pipe, it comes out like this in a byte[] array :
Length: 22 Bytes
0x06, 0x00, 0x00, 0x00, 4 bytes for array
0x00, 0x00, 0x00, 0x00, 2 bytes for build, 2 bytes for alignment?
0x15, 0xA3, 0x86, 0x3F, 8 bytes for double
0xBC, 0x44, 0xE4, 0x40,
0xA3, 0x02, 0x00, 0x00, 2 bytes for SVNChangeSet, 2 bytes alignment?
0x00, 0x00, 2 bytes for something else?
Alignment Questions
I believe this is called alignment in 4-byte boundries, correct?
What are the last two bytes for?
Now I'm trying (unsuccessfully) to marshal this into a C# struct.
[StructLayout(LayoutKind.Sequential)]
struct TAboutInfo
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] Version;
public ushort Build;
public double BuildDate;
public ushort SVNChangeSet;
}
IntPtr ptr = Marshal.AllocHGlobal(bytebuffer.Length);
Marshal.Copy(ptr, bytebuffer, 0, bytebuffer.Length);
TAboutInfo ta = (TAboutInfo)Marshal.PtrToStructure(ptr, typeof(TAboutInfo));
Marshal.FreeHGlobal(ptr);
C# Questions
This simply does not work, and I can't really figure out how to account for the alignment. I've tried explicit offsets but I'm coming up short.
I have many record types, some with members that are dynamic arrays of other records. I'd rather come up with a robust solution to converting these byte arrays into structures or objects.
Alignment is normally used by the compiler as an optimization. Actually every structure is padded to a multiple of 4 (or 8 I don't remember exactly).
Update: What I state above about alignment is not accurate. Have a read of David's answer for details on how aligned records are treated by the compiler. The Wikipedia article contains a reasonable overview: http://en.wikipedia.org/wiki/Data_structure_alignment
Anyway, you can use the Pack parameter to specify the alignment. A Pack value of 1 returns the exact size of the structure.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
About arrays, it's correct to use:
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public char[] someCharArray;
Just take care when you convert from structure to byte array that the array must match the declared size. Before converting, you should use Array.Resize if the content is shorter.
struct.someCharArray = "Hello".ToCharArray();
Array.Resize<char>(ref struct.someCharArray, 20);
About marshaling I use this method from byte[] to structure:
public static T ParseStructure<T>(byte[] array, int offset) where T : struct
{
if (array == null) throw new ArgumentNullException("array", "Input parameter cannot be null");
if (array.Length - offset < Marshal.SizeOf(typeof(T)))
Array.Resize<byte>(ref array, Marshal.SizeOf(typeof(T)) + offset);
int arraySize = array.Length - offset;
T returnItem;
// Allocate some unmanaged memory.
IntPtr buffer = Marshal.AllocHGlobal(arraySize);
// Copy the read byte array (byte[]) into the unmanaged memory block.
Marshal.Copy(array, offset, buffer, arraySize);
// Marshal the unmanaged memory block to a structure.
returnItem = (T)Marshal.PtrToStructure(buffer, typeof(T));
// Free the unmanaged memory block.
Marshal.FreeHGlobal(buffer);
return returnItem;
}
And this method does the opposite:
public static byte[] StructureToArray<T>(T structure) where T : struct
{
int objectSize = Marshal.SizeOf(structure);
byte[] result = new byte[objectSize];
IntPtr buffer = Marshal.AllocHGlobal(objectSize);
object dataStructure = (object)structure;
Marshal.StructureToPtr(dataStructure, buffer, true);
Marshal.Copy(buffer, result, 0, objectSize);
Marshal.FreeHGlobal(buffer);
return result;
}
Also, please use the following code to check the size calculated by the framework:
int objectSize = Marshal.SizeOf(structure);
Finally I found this nice article about marshalling.
I'm going to assume that your Delphi compiler is operating in the default mode and so is aligning records. I also assume that your Pascal code contains a simple typo where your array has 5 elements instead of 4.
The alignment of an aligned record is determined by the member with the largest alignment. The largest member is the 8 byte double. So the record has alignment 8. Its size is an exact multiple of its alignment.
Each individual field is aligned to match the field's alignment. The byte array has alignment 1 and can appear anywhere. The 2 byte integers must appear on 2 byte boundaries, and so on. Records may have padding at the end to ensure that arrays of the record will also be aligned. So the record has size that is a multiple of 8. Your record has size 24.
In your case, the padding is before the 8 byte double, and at the end of the record. If this padding at the end was not included, the 8 byte double would be mis-aligned in any arrays of your record.
There's no need to make any changes in your Delphi record and C# struct declarations. They are already declared correctly, and match each other perfectly.
You can use the SizeOf in Delphi and Marshal.SizeOf in C# to check the size of your structures. You will find that they match with the code in the question.
I cannot comment on how your code failed because you did not describe that failure. My main point is that any failure is not because of a mis-match between your structures. There's no rational explanation for the source of the number 22. I'd look to where that number comes from.
Finally, the answer that you accepted proposes using packed structures. There's no need to do that, I see no reason to do so, and it does not explain your problems.
I don't know what to call this, which makes googling harder.
I have an integer, say 3, and want to convert it to 11100000, that is, a byte with the value of the integers number of bits set, from the most significantly bit.
I guess it could be done with:
byte result = 0;
for(int i = 8; i > 8 - 3; i--)
result += 2 ^ i;
but is there anything faster / more nice or, preferably, standard library included in .net?
int n = 3; // 0..8
int mask = 0xFF00;
byte result = (byte) (mask >> n);
Because there are only a few possibilities, you could just cache them:
// Each index adds another bit from the left, e.g. resultCache[3] == 11100000.
byte[] resultCache = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0XF8, 0xFC, 0xFE, 0xFF };
You'd also get an exception instead of a silent error if you accidentally tried to get the value for n > 8.