Jump to content
  • Advertisement
Sign in to follow this  
starstriker1

Bizarre, inconsistent behaviour in file I/O

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've made a 2D skeletal animation animation editor for my current project. However, there's a problem: occasionally, an animation file will be saved but then appear "corrupted" when I attempt to load it again. The data will load correctly up until a certain point, where fread figures that it's hit the end of file and refuses to load any more data. I've done the math, and the file I'm loading is exactly the size that I'd expect it to be. Additionally, the issue only occurs sporadically... it appears almost completely random whether or not a file will be saved with such a bug. The only thing I can imagine that would cause this is that I'm accidentally writing some kind of end of file marker into my animation files, yet I haven't been able to find any information on the subject yet. Here's my code:
bool Animation::LoadFromFile(string &filename)
{
	//Open file
	FILE *file = fopen(filename.c_str(), "r");
	if(!file)
	{
		hge->System_Log("Couldn't load file: %s", filename.c_str());
		return false;
	}

	ClearExisting();
	
	int numKeyFrames = 0;
	fread(&numKeyFrames, sizeof(int), 1, file);
	int numBonesPerFrame = 0;
	fread(&numBonesPerFrame, sizeof(int), 1, file);

	for(int i = 0; i < numKeyFrames; i++)
	{
		float pos;
		fread(&pos, sizeof(float), 1, file);
		
		KeyFrame *temp = new KeyFrame;
		temp->position = pos;
		
		for(int j = 0; j < numBonesPerFrame; j++)
		{			
			BoneState *boneState = new BoneState;
			temp->boneStates.push_back(boneState);
			fread(&boneState->angle, sizeof(float), 1, file);
			fread(&boneState->lengthFactor, sizeof(float), 1, file);
		}

		keyFrames.push_back(temp);
	}

	//Close file
	if(fclose(file))
	{
		hge->System_Log("Couldn't close file after loading: %s", filename.c_str());
		return false;
	}
	return true;
}

bool Animation::SaveToFile(string &filename)
{
	//Open file
	FILE *file = fopen(filename.c_str(), "w");
	if(!file)
	{
		hge->System_Log("Couldn't save file: %s", filename.c_str());
		return false;
	}

	int numKeyFrames = (int)keyFrames.size();
	fwrite(&numKeyFrames, sizeof(int), 1, file);
	int numBonesPerFrame = (int)keyFrames[0]->boneStates.size();
	fwrite(&numBonesPerFrame, sizeof(int), 1, file);

	for(int i = 0; i < numKeyFrames; i++)
	{
		fwrite(&keyFrames->position, sizeof(float), 1, file);
		for(int j = 0; j < numBonesPerFrame; j++)
		{
			fwrite(&keyFrames->boneStates[j]->angle, sizeof(float), 1, file);
			fwrite(&keyFrames->boneStates[j]->lengthFactor, sizeof(float), 1, file);
		}
	}

	//Close file
	if(fclose(file))
	{
		hge->System_Log("Couldn't close file after saving: %s", filename.c_str());
		return false;
	}
	return true;
}



Does anyone have any insight as to how to fix this? The problem can be worked around, because not all files seem to be affected (and affected ones can be sometimes fixed by redoing the work that was lost), but it is a huge pain in the ass to lose 15 frames of an animation for no apparent reason. Thanks! [edit] By the way, I've spent a large amount of time debugging and I can guarantee that ferror isn't flagging anything in either function. When the errors occur, it's always in the load function and feof is always returning a nonzero value too early.

Share this post


Link to post
Share on other sites
Advertisement
I know, I know. Actually, I tried rewriting the code using fstream, but strangely enough it gave me the same problems, just with different files becoming unreadable. I'll chalk that up to inexperience, though.

Thanks, I didn't know there was a binary flag for that! I'll let you know if it fixes it.

Share this post


Link to post
Share on other sites
Nope, didn't work. It's operating the same way I saw it misbehave when I was using fstream with ios::binary... most files are opening correctly, some of the ones that weren't now do what they're supposed to, but some files that previously worked are incompatible!

I haven't checked file contents, but if it's anything like when I was using fstream, I'm getting junk values past as certain point in the file.

I'm obviously missing something here... is extra data being written into my files when I don't write them in binary mode? Does binary mode have any caveats I need to watch for? This entire thing is driving me nuts...

Share this post


Link to post
Share on other sites
Alright, I think I fixed it. I loaded all my existing animations in text mode and saved them in binary to convert them, and then loading them in binary worked fine.

Most files stays the same, actually, but a couple of them changed enough for the SVN to pick up on it. So I have a question: does writing to a file in text mode automatically put carriage returns after X number of bytes, or somesuch? I've never seen that in any sort of documentation, but that'd definitely explain my results.

Share this post


Link to post
Share on other sites
Text mode (the default in almost all I/O libraries) converts newlines (LF aka Line Feed, "\n", ASCII 10) to local-OS newlines (Unix: LF, Mac: CR (Carriage Return, ASCII 13), Windows CR+LF (one after the other)) when written to file. Reading in text mode converts local-OS newlines in the file to LF in memory.

Using binary mode results in no such translation.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!