ascii in binary files.

Started by
3 comments, last by Zahlman 17 years, 10 months ago
I want to write a binary file but I also need to have some text in it that links to outside files. I wrote some test code but when I write a string I always gte gibberish attached to the end of it. This program takes a string, writes the length of the string as an unsigned int then writes the string itself. The problem comes from reading the file after.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

void main()
{
	
	FILE *filePtr;
	filePtr = fopen("file.txt", "wb");

	string line = "textures/sometexture.tga";

	unsigned int length = (unsigned int)line.length();
	fwrite(&length, sizeof(unsigned int), 1, filePtr);
	fwrite(line.c_str(), length, 1, filePtr);

	line = "";
	length = 0;
	fclose(filePtr);

	filePtr = fopen("file.txt", "rb");
	fread(&length, sizeof(unsigned int), 1, filePtr);

	char *buffer = new char[length];
	fread(buffer, sizeof(char), length, filePtr);
	line = buffer;
	delete [] buffer;

	cout<<"Length= "<<length<<endl;
	cout<<line<<endl;
	fclose(filePtr);
}

this is the text file output: textures/sometexture.tga but when I read it back I get chinese characters and stuff appended. this is the frist time I tried to do this...I thought it would be simple.
Advertisement
You forgot the null terminator.

You neither wrote nor read the null terminator.

C strings suck, don't they?
To expand a little on what NotAYakk said:
unsigned int length = (unsigned int)line.length();
Should be:
unsigned int length = (unsigned int)line.length()+1;
added this and it seemed to work.

char *buffer = new char[length+1];
fread(buffer, sizeof(char), length, filePtr);
buffer[length] = NULL;
line = buffer;
delete [] buffer;

thanks.
You can do it that way, but doing your own memory management kinda sucks. Unfortunately you can't just resize a string's buffer and read in, because it isn't even guaranteed to have contiguous storage (for really long strings, that might actually be a bad idea). And fread() can't take a back_insert_iterator or anything that nice ;\ (On the other hand, why are you still using C file I/O?)

But, you can always make use of the one standard library container that *does* guarantee contiguous storage - std::vector - and also not have to worry about the null terminator:

vector<char> buffer(length);// with an 'istream myfile(ios::binary);', a binary read looks like:myfile.read(&buffer[0], length);// Note there's no need to distinguish a "block size" from an "element count".// Also, in C++, sizeof(char) == 1 by definition.line.assign(buffer.begin(), buffer.end());

This topic is closed to new replies.

Advertisement