Writing to a file

Started by
2 comments, last by the_edd 11 years, 10 months ago
Hi, i have this function where I must be misunderstanding something because it is not as expected and I cannot figure out whats going on. Hoping for some help smile.png


std::string CreateTempConvertedGfx(const std::string & name, const std::string & filename)
{
std::string handle = CreateHandle(name);
std::string tempFileName = "temps/" + handle + ".tmp";

TargaImage image;

if (!image.load(filename))
{
std::cout << "ERROR: Could not load targa image: " << filename << std::endl;
while(1);
}

int frames = 1;
int frameDelay = 10;
int frameWidth = 16;
int frameHeight = 16;

ReadGDFFile(filename, frames, frameDelay, frameWidth, frameHeight);

frames = image.getWidth() / frameWidth;

GRAPHIC_DATA gfxData;

strcpy(gfxData.m_handle, handle.c_str());

gfxData.m_frames = frames;
gfxData.m_frameDelay = frameDelay;
gfxData.m_frameWidth = frameWidth;
gfxData.m_frameHeight = frameHeight;

gfxData.m_textureWidth = image.getWidth();
gfxData.m_textureHeight = image.getHeight();
gfxData.m_textureSize = image.getSize();

std::ofstream dstFile(tempFileName);

if (dstFile.is_open() == false)
{
std::cout << "ERROR: Could not open dst: " << tempFileName << std::endl;
while(1);
}

long startp = dstFile.tellp();

dstFile.write((char *)&gfxData, sizeof(GRAPHIC_DATA)); // temp - THIS IS WRITING 61 BYTES WHEN GRAPHIC_DATA is 60 ?!

// temp
// these should be equal, and they are for Potion, the one with a gdf file
// if you remove the gdf file it stops working and any you add one too
// start to work
// why does having a gdf file making it work and not having one break it
long tellpp = dstFile.tellp();
if (tellpp != sizeof(GRAPHIC_DATA))
{
std::cout << "ERROR: " << tempFileName << " [" << tellpp << " / " << sizeof(GRAPHIC_DATA) << "] : " << startp << std::endl;
while(1);
}
// end temp

dstFile.write((char *)image.getImageData(), image.getSize());

dstFile.close();

return tempFileName;
}


The problem is, the line
dstFile.write((char *)&gfxData, sizeof(GRAPHIC_DATA));
After calling this I check the the position with tellp and it ends up 1 position ahead of where it should be (i think).

The weird thing is, this write only goes 1 position past IF I have a .gdf file (just a basic file with some info).


The output ill get is
ERROR: temps/Attribute_Damage.tmp [61/60] : 0

And this error is for all files where ReadGDFFile doesnt open anything. Here is the source to that incase


void ReadGDFFile(const std::string & filename, int & frames, int & frameDelay, int & frameWidth, int & frameHeight)
{
std::string gdfFilename = filename;
size_t end = gdfFilename.find_last_of(".");

if (end == std::string::npos)
{
std::cout << "ERROR: Invalid file name" << std::endl;
while(1);
}

gdfFilename = gdfFilename.substr(0, end + 1) + "gdf";

std::ifstream gdfFile(gdfFilename);

if (gdfFile.is_open())
{
std::string option;

while (gdfFile.eof() == false)
{
gdfFile >> option;

if (option == "frameDelay")
{
gdfFile >> frameDelay;
}
else if (option == "frameWidth")
{
gdfFile >> frameWidth;
}
else if (option == "frameHeight")
{
gdfFile >> frameHeight;
}
else
{
std::cout << "Unknown GDF attribute name: " << option;
while(1);
}
}

gdfFile.close();
}
}



const int MAX_GFX_NAME = 32;

#pragma pack(push, 1)

struct GRAPHIC_DATA
{
char m_handle[MAX_GFX_NAME];
int m_frames;
int m_frameDelay;
int m_frameWidth;
int m_frameHeight;
int m_textureWidth;
int m_textureHeight;
int m_textureSize;
};

#pragma pack(pop)



The thing is Im not sure how anything changes how much data is written. sizeof(GRAPHIC_DATA) should always be the same.

Please ask if you need more info. I have attached the source.
To test, compile, then drag and drop the "files" folder onto the exe in the debug folder.

Thanks for any help.
Advertisement

Hi, i have this function where I must be misunderstanding something because it is not as expected and I cannot figure out whats going on. Hoping for some help smile.png


std::string CreateTempConvertedGfx(const std::string & name, const std::string & filename)
{
std::string handle = CreateHandle(name);
std::string tempFileName = "temps/" + handle + ".tmp";

TargaImage image;

if (!image.load(filename))
{
std::cout << "ERROR: Could not load targa image: " << filename << std::endl;
while(1);
}


while(1) ?



int frames = 1;
int frameDelay = 10;
int frameWidth = 16;
int frameHeight = 16;

ReadGDFFile(filename, frames, frameDelay, frameWidth, frameHeight);

frames = image.getWidth() / frameWidth;

GRAPHIC_DATA gfxData;

strcpy(gfxData.m_handle, handle.c_str());

[/quote]
This strcpy call is susceptible to overflow. You should at least make sure handle.size() is strictly less than MAX_GFX_NAME before making the call.



gfxData.m_frames = frames;
gfxData.m_frameDelay = frameDelay;
gfxData.m_frameWidth = frameWidth;
gfxData.m_frameHeight = frameHeight;

gfxData.m_textureWidth = image.getWidth();
gfxData.m_textureHeight = image.getHeight();
gfxData.m_textureSize = image.getSize();

std::ofstream dstFile(tempFileName);

[/quote]
You probably want to pass std::ios::binary as a second argument to std::ofstream's constructor.



if (dstFile.is_open() == false)
{
std::cout << "ERROR: Could not open dst: " << tempFileName << std::endl;
while(1);
}

long startp = dstFile.tellp();

dstFile.write((char *)&gfxData, sizeof(GRAPHIC_DATA)); // temp - THIS IS WRITING 61 BYTES WHEN GRAPHIC_DATA is 60 ?!

[/quote]
I see you took care of padding, but you may want to consider endianness if this format is supposed to be portable, if you haven't already.



// temp
// these should be equal, and they are for Potion, the one with a gdf file
// if you remove the gdf file it stops working and any you add one too
// start to work
// why does having a gdf file making it work and not having one break it
long tellpp = dstFile.tellp();
if (tellpp != sizeof(GRAPHIC_DATA))

[/quote]
Presumably you mean to check (tellpp - startp) against the sizeof GRAPHIC_DATA? Though I honestly doubt it matters in this case.



[...]

dstFile.close();

[/quote]
FYI, the destructor of std::ofstream closes the file for you.


And this error is for all files where ReadGDFFile doesnt open anything. Here is the source to that incase


void ReadGDFFile(const std::string & filename, int & frames, int & frameDelay, int & frameWidth, int & frameHeight)
{
std::string gdfFilename = filename;
size_t end = gdfFilename.find_last_of(".");

if (end == std::string::npos)
{
std::cout << "ERROR: Invalid file name" << std::endl;
while(1);
}

gdfFilename = gdfFilename.substr(0, end + 1) + "gdf";

[/quote]
I don't think "end + 1" is correct.

This is possibly a good time to get to know your debugger a little better.
The while(1); just creates an infinite loop, essentially halting the program displaying the last error message.

The handle is checked before using strcpy (however it was done in the CreateHandle function I didn't give you the source on in the post).

I'll try the std::ios::binary as a second parameter, ty for the suggestion. smile.png

II thought the (end + 1) would return the position past the . (i.e. the extension)
Ill double check it though.

EDIT:

Not treating the file as binary was the problem, THANKS! :)

II thought the (end + 1) would return the position past the . (i.e. the extension)

Ah yes my mistake, I misunderstood your intention there. Apologies for that.


Not treating the file as binary was the problem, THANKS! smile.png
[/quote]
Glad it helped.

This topic is closed to new replies.

Advertisement