• 15
• 15
• 11
• 9
• 10

# Writing to a file

This topic is 2104 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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

 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.

To test, compile, then drag and drop the "files" folder onto the exe in the debug folder.

Thanks for any help.

##### Share on other sites

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

 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. Edited by e?dd

##### Share on other sites
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.

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! Edited by Azenris

##### Share on other sites

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!
[/quote]