fread: how to read n bytes from bin files

Hi! I have a binary file. It consists of records: 8 byte long, 4 byte float, 4 byte float, 4 byte float. I want to read the file into array Nx4. N - records number. How can I do it? I tried fread but without result.

1 Comment

Is it correct?
fid = fopen('acc-angle.bin', 'rb'); % открытие файла на чтение
if fid == -1 % проверка корректности открытия
error('File is not opened');
end
time=[];
ax=[];
ay=[];
az=[];
records_num=0;
while ~feof(fid)
time = [time; fread(fid,1,'int64')];
ax= [ax; fread(fid,1,'float32')];
ay= [ay; fread(fid,1,'float32')];
az= [az; fread(fid,1,'float32')];
records_num=records_num+1;
end
fclose(fid);

Sign in to comment.

 Accepted Answer

Guillaume
Guillaume on 7 Jul 2017
Edited: Guillaume on 8 Jul 2017
Is it correct? The easiest way for you to find out is to try.
fid = fopen('acc-angle.bin', 'rb')
There's no 'b' option for fopen permissions. 'r' is all that is needed for binary.
Otherwise, your code looks ok to me as long as your file has little endian encoding. A faster option would be to read all records at once using the skip parameter of fread, something like:
fid = fopen('acc-angle.bin', 'r');
time = fread(fid, Inf, 'int64', 12);
fseek(fid, 'bof', 8);
ax = fread(fid, Inf, 'single', 16);
fseek(fid, 'bof', 12);
ay = fread(fid, Inf, 'single', 16);
fseek(fid, 'bof', 16);
az = fread(fid, Inf, 'single', 16);
fclose(fid);

7 Comments

After each of those fread() you should fseek() to beginning of file offset by the sum of the sizes of all of the previous fields. That is, after each fread() you are left at end of file and need to reposition.
Guillaume
Guillaume on 7 Jul 2017
Edited: Guillaume on 7 Jul 2017
Oops! Yes, of course. Fixed.
If the file is large, I've found that multiple calls to fread is (order of magnitude) slowers than reading the whole file all in one go, even when these calls are just reading one value after another without any seeking.
Thanks a lot! But one mistake: In the last three lines 16 instead of 12. Am I right?
time = fread(fid, Inf, 'int64', 12);
fseek(fid, 8, 'bof');
ax = fread(fid, Inf, 'single', 16);
fseek(fid, 12, 'bof');
ay = fread(fid, Inf, 'single', 16);
fseek(fid, 16, 'bof');
az = fread(fid, Inf, 'single', 16);
Guillaume
Guillaume on 8 Jul 2017
Edited: Guillaume on 8 Jul 2017
Yes! Fixed as well.
It revealed, that I have to invert byte order for each field before reading. How can I do this?
If it's the same for the whole file, in the call to fopen:
fid = fopen('acc-angle.bin', 'r', 'b'); %b for big endian
If it varies per field, in the call to fread:
time = fread(fid, Inf, 'int64', 12, 'b');
At the time you do the fopen() you can specify a byte order that is to apply by default to future fread().
Or, for each fread() you can specify the byte order.
Or, you can swapbytes() after doing the reading.

Sign in to comment.

More Answers (1)

memmapfile allows you to declare patterns of fields and so is suitable for reading in repeated structures.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!