5
$\begingroup$

I have a binary file where each data is a 64-bit unsigned integer (little endian). For simplicity, let's say the data in testdata.bin file opened in HxD is:

enter image description here namely:

CA 35 58 C8 8C 00 01 00
87 88 6A C8 8C 00 02 00
5F B2 83 C9 8C 00 03 00
CB 5F 86 C9 8C 00 01 00

I want to read the bin file and separate each 64-bit data into two parts (48-bit for one, 16-bit for another). As an example, the data in the first row CA 35 58 C8 8C 00 01 00 will be separated to CA 35 58 C8 8C 00 and 01 00(notice that they are in little endian), and then read in decimal format as {604656645578, 1}. In this case, CA 35 58 C8 8C 00stands for 604656645578 and 01 00 is for 1.

For testing, one can create testdata.bin with the following codes:

hexnumber = {{"CA", "35", "58", "C8", "8C", "00", "01", "00"}, {"87", 
    "88", "6A", "C8", "8C", "00", "02", "00"}, {"5F", "B2", "83", 
    "C9", "8C", "00", "03", "00"}, {"CB", "5F", "86", "C9", "8C", 
    "00", "01", "00"}};
bincreate = {};
For[ii = 1, ii <= Length[hexnumber], ii++,
  For[kk = 1, kk <= 8, kk++,
    AppendTo[bincreate, 
      Interpreter["HexInteger"][hexnumber[[ii]][[kk]]]];
    ];
  ];

binname = "testdata.bin";
currentdirectory = NotebookDirectory[];
pSite = FileNameJoin[{currentdirectory, binname}];
If[FileExistsQ[binname] == False, binfile = CreateFile[pSite], 
 binfile = pSite;]
BinaryWrite[binfile, bincreate];

Q: I want to read the bin file and the results somehow in the following form:

{{604656645578, 1}, {604657846407, 2}, {604676272735, 3}, {604676448203, 1}}

i.e. 604656645578 is given by CA 35 58 C8 8C 00 in little endian.

I thought it might work by using BinaryReadList with Integer8 and recombine them for 48-bit and 16-bit, but not sure. Is it possible to do it in a simple way?

$\endgroup$

1 Answer 1

5
$\begingroup$
endianFlip[b_] := FromDigits[Reverse[IntegerDigits[b, 256]], 256]

{endianFlip[BitShiftRight[#, 16]], endianFlip[BitAnd[#, 2^16 - 1]]} & /@ 
 BinaryReadList["test.bin", "UnsignedInteger64", ByteOrdering -> 1]

This first reads in the whole file in big-endian unsigned 64-bit integers. For each entry it shifts down by two bytes for the first 48-bit item, and masks off the top 6 bytes with the bitwise AND to give the two bytes for the second item. Finally, both items are flipped back into little-endian.

... and it produces the result you want from your .bin file:

(* {{604656645578, 1}, {604657846407, 2}, {604676272735, 3}, {604676448203, 1}} *)
$\endgroup$
1
  • $\begingroup$ Thank you so much! That helps a lot! @flinty $\endgroup$
    – Xuemei
    May 27, 2021 at 5:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.