Read string of unknown size from binary using ifstream - C++

Started by
5 comments, last by L. Spiro 10 years, 7 months ago

Hello! I have my own custom binary model format and I am trying to read it using ifstream, but ran into a problem. I have a class called NXNode which contains the name of each scene node. The problem is that the name's size varies. How would I read the string correctly when I don't know it's size? I know BinaryReader.ReadString() does it without me specifying the size, so it must be possible with C++ too right? Thanks! smile.png

[EDIT: Here's some code if it helps]


NXNode::NXNode(ifstream* reader, NXNode* parent) : NXNode()
{
	if (parent != NULL)
		Parent = parent;
	
	reader->read((char*) &Name, sizeof(string));
	reader->read((char*)&HasChildren, sizeof(bool));
	reader->read((char*)&MeshCount, sizeof(short));
	reader->read((char*)&ChildCount, sizeof(short));
	
	float nums[16];
	for (int i = 0; i < 16; i++)
	{
		reader->read((char*) &nums[i], sizeof(float));
	}

	if (HasChildren)
	{
		Children = new NXNode[ChildCount];
		for (int i = 0; i < ChildCount; i++)
		{
			Children[i] = NXNode(reader, this);
		}
	}
}
Advertisement

What is usually done is either a few bytes are prefixed to the string that tell you how many characters are in it, or the string is NULL terminated (so you write the trailing '\0' when you write the string) and when you read you just keep reading until you hit the NULL character.

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

Just to throw more onto what was already said, it is typically preferred to store the length of the string and then read the whole string all at once instead of repeatedly reading a single character at a time for performance reasons.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Hello! So I now the length for each string in my file. In this case, the length is 7 (box.obj). Here's how it's setup now:


int nameLength;
reader->read((char*) &nameLength, sizeof(int));
reader->read((char*) &Name, sizeof(nameLength));

But now, it won't read. My app crashes. Am I doing that the write way? Thanks! :)

Because you are reading “sizeof(nameLength)” characters instead of “nameLength” characters.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Note that depending on the type of Name, reading and writing using &Name could be very bad ju-ju.

And while we are on that note of precautions-

If “Name” is some kind of pointer then it should be allocated to be able to hold nameLength characters (or (nameLength + 1) if the ternimator is not included).

If “nameLength” does not include the terminating '\0' character, it must be explicitly added since it is not being added during the read.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

This topic is closed to new replies.

Advertisement