5

I need to read binary files which consist of 19 float32 numbers followed by a unknown number of uint32 numbers. How can I read such a file in python?

In Matlab the equivalent looks like this:

fid = fopen('myFile.bin','r');
params = fread(fid,19,'float');
data = fread(fid,'uint32');
fclose(fid);

2 Answers 2

6

Use numpy.fromfile() method and pass a file handle to it with the corresponding number of items to read.

import numpy as np
with open('myFile.bin', 'rb') as f:
    params = np.fromfile(f, dtype=np.float32, count=19)
    data = np.fromfile(f, dtype=np.int32, count=-1) # I *assumed* here your ints are 32-bit

Postpend .tolist() to closing paranthesis of fromfile() (like this: np.fromfile(...).tolist()) if you want to get standard Python lists instead of numpy arrays.

Sign up to request clarification or add additional context in comments.

7 Comments

np.fromfile does require the number of elements it should read, so this method doesn't work in my case since the file size is unknown
@mcExchange Not true. Notice -1 in the argument list - I forgot to add it to my original answer - editing right now.
@mcExchange Actually, if you read docs (see link in the answer), counts is set to -1 by default and that is why I did not explicitly put it in the second call. From docs: count : int Number of items to read. -1 means all items (i.e., the complete file). and numpy.fromfile(file, dtype=float, count=-1, sep='') So, technically, last -1 in the second fromfile() is not required to read the rest of integer numbers.
@mcExchange "...this method doesn't work in my case since the file size is unknown" Have you actually tried it?
Note that by using numpy as proposed in this answer you will gain performance boost compared to solution from my answer.
|
1

For reading binary file I recomend using struct package

The solution can be written as follows:

import struct

f = open("myFile.bin", "rb")

floats_bytes = f.read(19 * 4)
# here I assume that we read exactly 19 floats without errors

# 19 floats in array
floats_array = struct.unpack("<19f", floats_bytes)

# convert to list beacause struct.unpack returns tuple
floats_array = list(floats_array)

# array of ints
ints_array = []

while True:
    int_bytes = r.read(4)

    # check if not eof
    if not int_bytes:
        break

    int_value = struct.unpack("<I", int_bytes)[0]

    ints_array.append(int_value)

f.close()

Note that I assumed your numbers are stored in little endian byte order, so I used "<" in format strings.

2 Comments

Wow, this looks intricate. The timing seems to be a bit slow though. Loading the same file takes 36ms in pyhton while in Matlab it takes < 1 ms. Still thanks for your proposal, I will check if it's fast enough for my application... I'll let you know
I get how this answers the first part of the question about the fixed amount of float, but how do you deal with an "unknown number of int" as mentioned in the question?

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.