Sign in to follow this  
thecoast47

reading binary data using physicsFS[Solved]

Recommended Posts

thecoast47    255
Basically i am trying to read a binary file stored in a zip folder.
The binary file in the zip folder stores information for individual polygons.


This is the class header.
This class is responsible for transferring information from ConvexHull objects that i'd like to store into binary files. Its also responsible for reading information from the binary file. Once that information is read i can create a ConvexHull object and then reinitialize the geometry object. (hope that made sense i dont know a better way to put that)


[source lang="cpp"]class Geometry{
static const unsigned int MAX_VERTEX_ELEMENTS = 50;
static const unsigned int MAX_CHAR_ELEMENTS = 10;

public:
Geometry();
~Geometry();

ConvexHull * loadGeometryIntoMemory(MultiGrid<ConvexHull> * hullGridPtr);
void storeHullData(ConvexHull * ch);
void writeHullDataToFile(std::ofstream & file);
void readHullDataFromFile(std::ifstream & file);
void readHullDataFromBuffer(std::istringstream& file);
void initAllFields();
private:
unsigned int vrecsFilled_;//V for vertex
unsigned int krecsFilled_;//K for keyword
char textureKeyword_[MAX_CHAR_ELEMENTS];
float vx_[MAX_VERTEX_ELEMENTS];
float vy_[MAX_VERTEX_ELEMENTS];
bool translate_;
float fakeFriction_;


};[/source]

This is how i write to my binary file:

[source lang="cpp"]void Geometry::writeHullDataToFile(std::ofstream & file){
file.write((char*)&vrecsFilled_,sizeof(vrecsFilled_));

for(unsigned int K = 0; K < vrecsFilled_;K++){
float & x = vx_[K];
float & y = vy_[K];
file.write((char*)&x,sizeof(x));
file.write((char*)&y,sizeof(y));
}

file.write((char*)&krecsFilled_,sizeof(krecsFilled_));
for(unsigned int K = 0; K < krecsFilled_;K++){
char & c = textureKeyword_[K];
file.write((char*)&c,sizeof©);
}


//write parameters last
file.write((char*)&fakeFriction_,sizeof(fakeFriction_));
file.write((char*)&translate_,sizeof(translate_));
}[/source]


This is where i load the binary file into a buffer from the zip folder (using PhyicsFS) and attempt to read it.
I try read the binary data by calling the method "readHullDataFromBuffer(file);"

[source lang="cpp"] static void loadGeometryFromArchive(std::vector<std::string>& pathList,HullRegistry* hRegistry,MultiGrid<ConvexHull>* hullGrid){
PHYSFS_sint64 file_size = -1;
int length_read = 0;
char * bytes = NULL;
unsigned int listSize = 0;
Geometry primitiveData;
ConvexHull * currentHull = NULL;

for(unsigned int K = 0; K < pathList.size();K++){
std::string& p = pathList[K];
std::string path ="geometry/"+p;

if(PHYSFS_exists(path.data()) == 1){
//create file and stream bytes into a buffer
PHYSFS_file* myfile = PHYSFS_openRead(path.data());
file_size = PHYSFS_fileLength(myfile);
bytes = new char[file_size];

//writes the bytes from file in archive to bytes array
length_read = PHYSFS_read(myfile, bytes,1,PHYSFS_fileLength(myfile));

const char * errList = PHYSFS_getLastError();
_cprintf(errList);


//Okay now i've got the binary file loaded in the buffer
//i can only read the first number in the file before errors occur
std::istringstream file(bytes,std::istringstream::binary | std::istringstream::in);

//the first 4 bytes of the geometry file contains a number that represents the amount of polygons written to the file.
file.read((char*)&listSize,sizeof(listSize));// i succesfully read the correct number,however,this is where my luck ends

for(unsigned int K = 0; K < listSize;K++){
primitiveData.initAllFields();
primitiveData.readHullDataFromBuffer(file);//I then attempt to read each record using the buffer but this fails
currentHull = primitiveData.loadGeometryIntoMemory(hullGrid);
hRegistry->getStaticHullList().push_back(currentHull);
}

delete[] bytes;
PHYSFS_close(myfile);
}
}
}[/source]

I figured I could use std::istringstream like i would use std::ifsream.
But with this I can only read the first number in the binary file before i get errors.

[source lang="cpp"]void Geometry::readHullDataFromBuffer(std::istringstream& file){
file.read((char*)&vrecsFilled_,sizeof(vrecsFilled_));

for(unsigned int K = 0; K < vrecsFilled_;K++){
float & x = vx_[K];
float & y = vy_[K];

file.read((char*)&x,sizeof(x));
file.read((char*)&y,sizeof(y));
}

file.read((char*)&krecsFilled_,sizeof(krecsFilled_));
for(unsigned int K = 0; K < krecsFilled_;K++){
char & c = textureKeyword_[K];
file.read((char*)&c,sizeof©);
}


file.read((char*)&fakeFriction_,sizeof(fakeFriction_));
file.read((char*)&translate_,sizeof(translate_));
}[/source]

Basically, after i read the first number in the array, file.fail() becomes true and, anything after that is 0;
Can someone tell me why the previous method fails at the first character?
Is this an issue with PhysicsFS or is it my own code?


Okay so i solved my own issue. I basically just track the position of the array and then use memcpy to read the values.
Here is what i now use to read the records:

[source lang="cpp"]void Geometry::readHullDataFromBuffer(char * bytes,long & position){
memcpy(&vrecsFilled_,bytes+position,sizeof(vrecsFilled_));
position+=sizeof(vrecsFilled_);


for(unsigned int K = 0; K < vrecsFilled_;K++){
float & x = vx_[K];
float & y = vy_[K];

memcpy(&x,bytes+position,sizeof(x));
position+=sizeof(x);

memcpy(&y,bytes+position,sizeof(y));
position+=sizeof(y);
}


memcpy(&krecsFilled_,bytes+position,sizeof(krecsFilled_));
position+=sizeof(krecsFilled_);

for(unsigned int K = 0; K < krecsFilled_;K++){
char & c = textureKeyword_[K];
memcpy(&c,bytes+position,sizeof©);
position+=sizeof©;
}

memcpy(&fakeFriction_,bytes+position,sizeof(fakeFriction_));
position+=sizeof(fakeFriction_);

memcpy(&translate_,bytes+position,sizeof(translate_));
position+=sizeof(translate_);
}[/source]

Thank you all for your help.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this