7

Everything I'm finding via google is garbage... Note that I want the answer in C, however if you supplement your answer with a C++ solution as well then you get bonus points!

I just want to be able to read some floats into an array from a binary file

EDIT: Yes I know about Endian-ness... and no I don't care how it was stored.

DigitalZebra
  • 39,494
  • 39
  • 114
  • 146

7 Answers7

19

How you have to read the floats from the file completely depends on how the values were saved there in the first place. One common way could be:

void writefloat(float v, FILE *f) {
  fwrite((void*)(&v), sizeof(v), 1, f);
}

float readfloat(FILE *f) {
  float v;
  fread((void*)(&v), sizeof(v), 1, f);
  return v;
}
Michael Myers
  • 188,989
  • 46
  • 291
  • 292
sth
  • 222,467
  • 53
  • 283
  • 367
  • 1
    Thank you, I don't know why the hell it was so hard for everyone else I was finding on google to write that simple statement. I swear to God people just like making things more complicated for the hell of it. – DigitalZebra Sep 14 '09 at 17:22
  • 2
    Mind that the byte order does matter here if you move the file across platforms. – xtofl Sep 14 '09 at 17:27
  • I believe anything x86 or x64 will have the same endianness... correct? – DigitalZebra Sep 14 '09 at 17:29
  • What would I have to do if I wanted to read a fixed number of floats from th file? Thanks – DigitalZebra Sep 14 '09 at 18:15
  • 4
    @Polaris878: Call that function a fixed number of times? – sth Sep 14 '09 at 18:22
  • @Polaris878: just use `fread()` without the wrapper function (see my answer http://stackoverflow.com/questions/1422817/how-to-read-a-float-from-binary-file-in-c/1422869#1422869 ) - the sole reason for existence of this function with distinct parameters for object size and object count is to allow bulk reading – Christoph Sep 14 '09 at 18:29
  • It was so hard, because it was so obvious I imagine that most people must have assumed that you must have been having problems *exactly* because of all the gotcha's they were warning about. They were trying to help, and your question started out petulant; I don't know why they bothered. After all you only asked about reading; if your code wrote the file, you'd surely have known how to read it back? The solution given only works if the values are read and written by the same architcture. And it is not only an endian'ness issue, it is size and encoding as well. – Clifford Sep 14 '09 at 19:04
  • @ Clifford, yes I know it might seem obvious... however I was writing my file using the .NET libraries and had to read it in C from another process. I'm not familiar with many of the old school C APIs... Sorry I should've made that clear. – DigitalZebra Sep 15 '09 at 23:03
5
float f;
if(read(fd,&f,sizeof(f))==sizeof(f))
    printf("%f\n",f);
else
    printf("oops\n");

Provided that it's written as compatible binary representation.

read for file descriptors, fread for FILE*s and istream::read for c++ iostreams. Pick whatever pleases you:

read(fd,&f,sizeof(f))==sizeof(f)

fread(&f,sizeof(f),1,fp)==1

fin.read((char*)&f,sizeof(f)).gcount()==sizeof(f)
Michael Krelin - hacker
  • 138,757
  • 24
  • 193
  • 173
3

You could use fread. (Note the the API is for C, even though the website says C++ reference :))

vpram86
  • 5,860
  • 4
  • 28
  • 40
  • 4
    Bear in mind that depending on whether the float was written by a machine with different endian-ness then you may have to reorder the bytes after reading. – Jherico Sep 14 '09 at 17:16
3

Use fread() from <stdio.h>. The assertions should be replaced with actual error handling code.

#include <stdio.h>
#include <assert.h>

#define countof(ARRAY) (sizeof (ARRAY) / sizeof *(ARRAY))

float data[5];

FILE *file = fopen("foo.bin", "rb");
assert(file);

size_t n = fread(data, sizeof(float), countof(data), file);
assert(n == countof(data));

Keep in mind that you might run into endian issues if you transfer files between different architectures.

Christoph
  • 164,997
  • 36
  • 182
  • 240
2

If the file is all "float" and you wanted to read it X number of times, all you have to do is this:

FILE *fp;

if((fp=fopen("filename.whatever", "rb"))==NULL)
 return 0;

fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);

float *f = (float *)malloc(sizeof(float)*size);
if(f==NULL)
{
 fclose(fp);
 return 0;
}

if(fread(f, sizeof(float), size, fp)!=size)
{
 fclose(fp);
 return 0;
}

fclose(fp);

// do something with f
Daniel
  • 374
  • 2
  • 5
1
FILE *thisFile=fopen("filename","fb");
float myFloat;
fscanf(thisFile,"%f",&myFloat);
fclose(thisFile);

This works if the data is written using fprintf (implementation specific)
However, you can also typecast your float to int32 and save , load and typecast.

std::fstream thisFile;
thisFile.open("filename",ios::read|ios::binary);
float myFloat;
thisFile>>myFloat;
thisFile.close();

May be wrong (I haven't used the C++ F.IO functions for a loooong loooong time)

aviraldg
  • 9,531
  • 6
  • 41
  • 56
  • O.P. asked for files in binary format. This gives files in Ascii, which is easier to read, but not what was asked for. Sorry. – DragonLord Apr 05 '12 at 07:27
0

If these values are sequentially placed into a binary file you can do a read of sizeof(float) bytes per float value into a character array. You can then cast these into a float value.

Charles
  • 2,615
  • 3
  • 29
  • 35