1

I'm sure this must be a common problem but can't seem to find an equivalent question* or example.

I have a binary file that is a series of 4 byte floats. I am reading into a vector that is sized by the length of the file (divided by the size of my float). I have used the bytesToFloat method from another post. When printing out the data my code returns the same value for all data points. What's wrong?

*Sorry to the admins if I have missed it.

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

typedef unsigned char uchar;

float bytesToFloat(uchar b0, uchar b1, uchar b2, uchar b3);

int main()
{
int i,j;
char u[4];
// Open  file
ifstream file;
file.open("file.dat");
// Find file size in bytes
file.seekg(0,ios::end);
double size = 0;
size = file.tellg();
file.seekg(0,ios::beg);

vector<float> data;
data.resize(size/4);
i=0;
while(i<size/4)
{
    j=0;
    while(j<4)
    {
        file.read(&u[j],1);
        j++;
    }
    data[i] = bytesToFloat(u[0],u[1],u[2],u[3]);

    cout << data[i]<< endl;
    i++;
}

// End program
file.close();
return 0;
}

float bytesToFloat(uchar b0, uchar b1, uchar b2, uchar b3)
{
float output;

*((uchar*)(&output) + 3) = b0;
*((uchar*)(&output) + 2) = b1;
*((uchar*)(&output) + 1) = b2;
*((uchar*)(&output) + 0) = b3;

return output;
}
Community
  • 1
  • 1
Tom Wilkinson
  • 111
  • 2
  • 7
  • What happens if you drop all those loops, and just do `file.read(&data[0], size);` (right after `resize` call)? Make `size` an integer while you are at it. Also, how do you know your file does **not** in fact contain copies of the same value? – Igor Tandetnik Oct 11 '14 at 01:10
  • I tried the file.read method preivously and it only outputs the hex values not the float itself. This is why I am try to re-construct the float from its individual bytes. I opened the file in Visual Studio and the hex values are different. Also it was randomly generated from another piece of code I wrote that generates a series of random floats (and I have checked the output of that program). – Tom Wilkinson Oct 13 '14 at 08:51
  • What do you mean, "it only outputs"? `read` doesn't output anything. – Igor Tandetnik Oct 13 '14 at 15:15
  • I was sending the values in `buffer` obtained using `file.read` to cout. It printed hex values instead of the floats I expected it to store. – Tom Wilkinson Oct 14 '14 at 10:40
  • There's no variable named `buffer` in the code you've shown. – Igor Tandetnik Oct 14 '14 at 14:06
  • Sorry I've added a lot to my code since I first posted and forgot that `vector buffer` wasn't in the code placed here (just in my answer). – Tom Wilkinson Oct 14 '14 at 14:23

1 Answers1

0

So with a bit of effort and Igor's comment I was able to solve the problem. The following function reads everything into a buffer vector.

vector<char> buffer;

void fill() {
string filename = "";
cout << "Please enter a filename:\n>";
getline(cin, filename);

ifstream file(filename.c_str());

if (file) {
    file.seekg(0,std::ios::end);
    streampos length = file.tellg();
    cout<< length << endl;
    file.seekg(0,std::ios::beg);
    file.seekg(540,'\0');

    length-=540;
    buffer.resize(length);
    file.read(&buffer[0],length);
}
}

Then later on I call bytesToFloat in a loop. The endian-ness of bytesToFloat was incorrect so has now been reversed and it outputs the same values as my original file (I made my random file generator output a plain text version for comparison).

Tom Wilkinson
  • 111
  • 2
  • 7
  • Did you mean to skip the first 540 bytes of your file? That's what `file.seekg(540,'\0');` does. In any case, I'm pretty sure `file.read((char*)&data[0], length)` would have had the same effect (with `data` being `vector`, resized appropriately), without the need of `bytesToFloat`. – Igor Tandetnik Oct 13 '14 at 15:18
  • I was skipping a header of fixed byte length in the file (I didn't mention that before for simplicity). I tried using the method you suggest before but couldn't get it to work (I kept getting errors to do with converting to char). – Tom Wilkinson Oct 14 '14 at 10:37
  • The way you calculate `length` doesn't account for this fixed header. And yes, I forgot the need to cast to `char*` in my original suggestion. With the cast, you should be able to read directly into `data`. – Igor Tandetnik Oct 14 '14 at 14:08
  • I have fixed `length` in my code my removing the skip from it. I'll edit my response above. – Tom Wilkinson Oct 14 '14 at 14:25