views:

27

answers:

1

I have an array of a large structure that I am trying to output to hard drive. I seem to be able to write to hard drive just fine (though it's difficult to verify by looking at the binary data), however when I try to read it back, I always end up with a garbled mess. Any ideas what I'm doing wrong?

here's the structure configuration:

class xyz
{
public:
    double x, y, z;
};
class trianglePackage
{
public:

    int score;
    int position;

    xyz contactCoordinates;
    xyz normalVector;
    xyz locatorOffset;

};
class quadanglesOutput
{
public:

    int locator1position, locator2position, locator3position, locator4position;

    xyz centroid;

    int surfaceAreaScore;
    int centroidDifferance1Score;
    int centroidDifferance2Score;
    int minDistance1Score;
    int minDistance2Score;

    int totalLocatorScore;
    int totalHullScore;
    int totalScore;

    double surfaceArea;
    double centroidDifferance1;
    double centroidDifferance2;
    double minDistance1;
    double minDistance2;

    int hull;

    trianglePackage locator1, locator2, locator3, locator4;
};

and here are the read/write functions I'm using:

void outputQuadangleOutput(quadanglesOutput* output, string description, param parameters)
{

    string outputName = parameters.fileName + " " + description + ".bin";
    cout << "Output " << outputName.c_str() << "...";
    ofstream output2;
    output2.open(outputName.c_str());
    output2.write(reinterpret_cast<char*>(output), streamsize(parameters.topXlist * sizeof(quadanglesOutput)));
    output2.close();
    cout << "done" << endl;

}
void readIn(quadanglesOutput* pointer, param parameters, string description)
{
    string fileName = parameters.fileName + " " + description + ".bin";
    cout << "openining " << fileName << "...";
    ifstream readFile;
    readFile.open(fileName.c_str());
    readFile.read(reinterpret_cast<char*>(pointer), (parameters.topXlist * sizeof(quadanglesOutput)));
    readFile.close();
    cout << "done" << endl;
}

Typically the arrays of structures are about 100 in length, but usually only about the first 25 read back correctly, everything else is default uninitialized data.

I'm 99% sure that it's something wrong with my code, however is there a possibility it has something to do with four byte alignment?

Thanks.

+1  A: 

It may be an issue with byte alignment, use pragma. try wrap classes around with

#PRAGMA PACK PUSH(1)
....
#PRAGMA PACK POP

or

#PRAGMA PACK(1)
struct{
..
}

Try those as well:
Force binary flag for the stream.

ios_base::binary

readFile.open(fileName.c_str(), ios_base::binary);

Try to flush the the stream.

stream.write(...)
stream.flush()

//i know that close() should flush it.

UPDATE:
Everything works for me:

#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>

using namespace std;
#pragma pack(1)
class xyz
{
public:
    double x, y, z;
};

#pragma pack(1)
class trianglePackage
{
public:

    int score;
    int position;

    xyz contactCoordinates;
    xyz normalVector;
    xyz locatorOffset;

};

#pragma pack(1)
class quadanglesOutput
{
public:

    int locator1position, locator2position, locator3position, locator4position;

    xyz centroid;

    int surfaceAreaScore;
    int centroidDifferance1Score;
    int centroidDifferance2Score;
    int minDistance1Score;
    int minDistance2Score;

    int totalLocatorScore;
    int totalHullScore;
    int totalScore;

    double surfaceArea;
    double centroidDifferance1;
    double centroidDifferance2;
    double minDistance1;
    double minDistance2;

    int hull;

    trianglePackage locator1, locator2, locator3, locator4;
};

class param
{
public:
    string fileName;
    int topXlist;
};


void outputQuadangleOutput(quadanglesOutput* output, string description, param parameters)
{

    string outputName = parameters.fileName + " " + description + ".bin";
    cout << "Output " << outputName.c_str() << "...";
    ofstream output2;
    output2.open(outputName.c_str());
    output2.write(reinterpret_cast<char*>(output), streamsize(parameters.topXlist * sizeof(quadanglesOutput)));
    output2.close();
    cout << "done" << endl;

}
void readIn(quadanglesOutput* pointer, param parameters, string description)
{
    string fileName = parameters.fileName + " " + description + ".bin";
    cout << "openining " << fileName << "...";
    ifstream readFile;
    readFile.open(fileName.c_str());
    readFile.read(reinterpret_cast<char*>(pointer), (parameters.topXlist * sizeof(quadanglesOutput)));
    readFile.close();
    cout << "done" << endl;
}



int main(int argc, char *argv[])
{

    quadanglesOutput a = {0};
    cout<<"total score:"<<a.totalScore<<endl;
    cout<<"locator position:"<<a.totalScore<<endl;
    cout<<"locator position:"<<a.locator1.position<<endl;
    cout<<"locator position:"<<a.locator2.normalVector.y <<endl;
    cout<<"sizeof quadangsomething:"<<sizeof(quadanglesOutput)<<endl;
    a.totalScore=1;
    a.locator1.position=333445;
    a.locator2.normalVector.y = 999.3224;
    cout<<"total score:"<<a.totalScore<<endl;
    cout<<"locator position:"<<a.locator1.position<<endl;
    cout<<"locator position:"<<a.locator2.normalVector.y <<endl;
    param p = {"C:/", 1};
    outputQuadangleOutput(&a, "file1", p);

    quadanglesOutput *b = new quadanglesOutput();
    readIn(b, p, "file1");
    cout<<"new total score:"<<b->totalScore<<endl;
    cout<<"new locator position:"<<b->locator1.position<<endl;
    cout<<"new locator position:"<<b->locator2.normalVector.y <<endl;

    delete b;





    string asdf;
    cin>>asdf;

};

OUTPUT:
total score:0
locator position:0
locator2.normalVector.y :0
sizeof quadangsomething:436
total score:1
locator position:333445
locator2.normalVector.y :999.322
Output C:/ file1.bin...done
openining C:/ file1.bin...done
new total score:1
new locator position:333445
new locator2.normalVector.y :999.322

without pragma it's still correct but you can see the difference in size:

sizeof quadangsomething:440

But packing it is good when sending structures over network.
Because here system alligns it always in the same fashion.

bua
Hmm, it's still doing the same thing as before. First 25 read entries are good, rest are garbled.
Faken
The binary flag seems to have even reduced the number of properly read values, now it only reads the first 10 elements before producing a seemingly random output (as opposed to previously outputting "CD" in hex code over and over again).
Faken
@faken: Did you use binary mode for in- and output?
Georg Fritzsche
I've tested it and it works. (visual express 9.0). I'm almost sure that you invoke of readIn function is wrong (you haven't post that code). You need to allocate structure and pass pointer to it.
bua
@George: Ah! That was my mistake, it was that i forgot to put the binary flat on both input and output functions. Thank you, though full credit goes to bau for posing it first, but thank you for drawing my attention to it a second time. Thanks guys, your awesome!
Faken